svf-tools 1.0.993 → 1.0.994

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.993",
3
+ "version": "1.0.994",
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": {
@@ -31,13 +31,13 @@
31
31
  #define RCG_H_
32
32
 
33
33
  #include "Graphs/CallGraph.h"
34
- #include "MemoryModel/PointerAnalysisImpl.h"
35
34
 
36
35
  namespace SVF
37
36
  {
38
37
 
39
38
  class SVFModule;
40
39
  class ThreadAPI;
40
+ class PointerAnalysis;
41
41
  /*!
42
42
  * PTA thread fork edge from fork site to the entry of a start routine function
43
43
  */
@@ -201,7 +201,8 @@ public:
201
201
  /// whether this call instruction has a valid call graph edge
202
202
  inline bool hasThreadForkEdge(const CallICFGNode* cs) const
203
203
  {
204
- return callinstToThreadForkEdgesMap.find(cs) != callinstToThreadForkEdgesMap.end();
204
+ return callinstToThreadForkEdgesMap.find(cs) !=
205
+ callinstToThreadForkEdgesMap.end();
205
206
  }
206
207
  inline ForkEdgeSet::const_iterator getForkEdgeBegin(const CallICFGNode* cs) const
207
208
  {
@@ -345,8 +346,8 @@ public:
345
346
 
346
347
  /// Add direct/indirect thread fork edges
347
348
  //@{
348
- void addDirectForkEdge(const CallICFGNode* cs);
349
- void addIndirectForkEdge(const CallICFGNode* cs, const SVFFunction* callee);
349
+ bool addDirectForkEdge(const CallICFGNode* cs);
350
+ bool addIndirectForkEdge(const CallICFGNode* cs, const SVFFunction* callee);
350
351
  //@}
351
352
 
352
353
  /// Add thread join edges
@@ -34,7 +34,7 @@
34
34
  #include <signal.h>
35
35
 
36
36
  #include "Graphs/CHG.h"
37
- #include "Graphs/CallGraph.h"
37
+ #include "Graphs/ThreadCallGraph.h"
38
38
  #include "Graphs/SCC.h"
39
39
  #include "MemoryModel/AbstractPointsToDS.h"
40
40
  #include "MemoryModel/ConditionalPT.h"
@@ -199,6 +199,10 @@ protected:
199
199
  /// On the fly call graph construction
200
200
  virtual void onTheFlyCallGraphSolve(const CallSiteToFunPtrMap& callsites, CallEdgeMap& newEdges);
201
201
 
202
+ /// On the fly thread call graph construction respecting forksite
203
+ virtual void onTheFlyThreadCallGraphSolve(const CallSiteToFunPtrMap& callsites,
204
+ CallEdgeMap& newForkEdges);
205
+
202
206
  /// Normalize points-to information for field-sensitive analysis,
203
207
  /// i.e., replace fieldObj with baseObj if it is field-insensitive
204
208
  virtual void normalizePointsTo();
@@ -457,7 +457,7 @@ inline bool isBarrierWaitCall(const CallICFGNode* cs)
457
457
 
458
458
  /// Return sole argument of the thread routine
459
459
  //@{
460
- inline const SVFValue* getActualParmAtForkSite(const CallICFGNode* cs)
460
+ inline const SVFVar* getActualParmAtForkSite(const CallICFGNode* cs)
461
461
  {
462
462
  return ThreadAPI::getThreadAPI()->getActualParmAtForkSite(cs);
463
463
  }
@@ -38,6 +38,7 @@ namespace SVF
38
38
  class SVFModule;
39
39
  class ICFGNode;
40
40
  class CallICFGNode;
41
+ class SVFVar;
41
42
 
42
43
  /*
43
44
  * ThreadAPI class contains interfaces for pthread programs
@@ -128,11 +129,16 @@ public:
128
129
  /// Note that, it could be function type or a void* pointer
129
130
  const SVFValue* getForkedFun(const CallICFGNode *inst) const;
130
131
 
131
- /// Return the forth argument of the call,
132
+ /// Return the actual param of forksite
132
133
  /// Note that, it is the sole argument of start routine ( a void* pointer )
133
- const SVFValue* getActualParmAtForkSite(const CallICFGNode *inst) const;
134
+ const SVFVar* getActualParmAtForkSite(const CallICFGNode *inst) const;
135
+
136
+ /// Return the formal parm of forked function (the first arg in pthread)
137
+ const SVFVar* getFormalParmOfForkedFun(const SVFFunction* F) const;
134
138
  //@}
135
139
 
140
+
141
+
136
142
  /// Return true if this call create a new thread
137
143
  //@{
138
144
  bool isTDFork(const CallICFGNode *inst) const;
@@ -47,6 +47,8 @@ namespace SVF
47
47
 
48
48
  class SVFModule;
49
49
 
50
+ class ThreadCallGraph;
51
+
50
52
  /*!
51
53
  * Abstract class of inclusion-based Pointer Analysis
52
54
  */
@@ -54,6 +56,9 @@ typedef WPASolver<ConstraintGraph*> WPAConstraintSolver;
54
56
 
55
57
  class AndersenBase: public WPAConstraintSolver, public BVDataPTAImpl
56
58
  {
59
+ public:
60
+ typedef OrderedMap<const CallICFGNode*, NodeID> CallSite2DummyValPN;
61
+
57
62
  public:
58
63
 
59
64
  /// Constructor
@@ -81,11 +86,19 @@ public:
81
86
  /// Finalize analysis
82
87
  virtual void finalize() override;
83
88
 
84
- /// Implement it in child class to update call graph
85
- virtual inline bool updateCallGraph(const CallSiteToFunPtrMap&) override
86
- {
87
- return false;
88
- }
89
+ /// Update call graph
90
+ virtual bool updateCallGraph(const CallSiteToFunPtrMap&) override;
91
+
92
+ /// Update thread call graph
93
+ virtual bool updateThreadCallGraph(const CallSiteToFunPtrMap&, NodePairSet&);
94
+
95
+ /// Connect formal and actual parameters for indirect forksites
96
+ virtual void connectCaller2ForkedFunParams(const CallICFGNode* cs, const SVFFunction* F,
97
+ NodePairSet& cpySrcNodes);
98
+
99
+ /// Connect formal and actual parameters for indirect callsites
100
+ virtual void connectCaller2CalleeParams(const CallICFGNode* cs, const SVFFunction* F,
101
+ NodePairSet& cpySrcNodes);
89
102
 
90
103
  /// Methods for support type inquiry through isa, cast, and dyn_cast:
91
104
  //@{
@@ -123,6 +136,9 @@ public:
123
136
  }
124
137
  //@}
125
138
 
139
+ /// Add copy edge on constraint graph
140
+ virtual inline bool addCopyEdge(NodeID src, NodeID dst) = 0;
141
+
126
142
  /// dump statistics
127
143
  inline void printStat()
128
144
  {
@@ -160,6 +176,11 @@ public:
160
176
  protected:
161
177
  /// Constraint Graph
162
178
  ConstraintGraph* consCG;
179
+ CallSite2DummyValPN
180
+ callsite2DummyValPN; ///< Map an instruction to a dummy obj which
181
+ ///< created at an indirect callsite, which invokes
182
+ ///< a heap allocator
183
+ void heapAllocatorViaIndCall(const CallICFGNode* cs, NodePairSet& cpySrcNodes);
163
184
  };
164
185
 
165
186
  /*!
@@ -171,7 +192,6 @@ class Andersen: public AndersenBase
171
192
 
172
193
  public:
173
194
  typedef SCCDetection<ConstraintGraph*> CGSCC;
174
- typedef OrderedMap<const CallICFGNode*, NodeID> CallSite2DummyValPN;
175
195
 
176
196
  /// Constructor
177
197
  Andersen(SVFIR* _pag, PTATY type = Andersen_WPA, bool alias_check = true)
@@ -243,7 +263,6 @@ public:
243
263
  protected:
244
264
 
245
265
  CallSite2DummyValPN callsite2DummyValPN; ///< Map an instruction to a dummy obj which created at an indirect callsite, which invokes a heap allocator
246
- void heapAllocatorViaIndCall(const CallICFGNode* cs,NodePairSet &cpySrcNodes);
247
266
 
248
267
  /// Handle diff points-to set.
249
268
  virtual inline void computeDiffPts(NodeID id)
@@ -311,12 +330,6 @@ protected:
311
330
  return false;
312
331
  }
313
332
 
314
- /// Update call graph for the input indirect callsites
315
- virtual bool updateCallGraph(const CallSiteToFunPtrMap& callsites);
316
-
317
- /// Connect formal and actual parameters for indirect callsites
318
- void connectCaller2CalleeParams(const CallICFGNode* cs, const SVFFunction* F, NodePairSet& cpySrcNodes);
319
-
320
333
  /// Merge sub node to its rep
321
334
  virtual void mergeNodeToRep(NodeID nodeId,NodeID newRepId);
322
335
 
@@ -23,7 +23,6 @@ class Steensgaard : public AndersenBase
23
23
  public:
24
24
  typedef Map<NodeID, NodeID> NodeToEquivClassMap;
25
25
  typedef Map<NodeID, Set<NodeID>> NodeToSubsMap;
26
- typedef OrderedMap<const CallICFGNode*, NodeID> CallSite2DummyValPN;
27
26
 
28
27
  /// Constructor
29
28
  Steensgaard(SVFIR* _pag) : AndersenBase(_pag, Steensgaard_WPA, true) {}
@@ -46,7 +45,7 @@ public:
46
45
  steens = nullptr;
47
46
  }
48
47
 
49
- virtual void solveWorklist();
48
+ virtual void solveWorklist() override;
50
49
 
51
50
  void processAllAddr();
52
51
 
@@ -69,18 +68,18 @@ public:
69
68
  //@}
70
69
 
71
70
  /// Operation of points-to set
72
- virtual inline const PointsTo& getPts(NodeID id)
71
+ virtual inline const PointsTo& getPts(NodeID id) override
73
72
  {
74
73
  return getPTDataTy()->getPts(getEC(id));
75
74
  }
76
75
  /// pts(id) = pts(id) U target
77
- virtual inline bool unionPts(NodeID id, const PointsTo& target)
76
+ virtual inline bool unionPts(NodeID id, const PointsTo& target) override
78
77
  {
79
78
  id = getEC(id);
80
79
  return getPTDataTy()->unionPts(id, target);
81
80
  }
82
81
  /// pts(id) = pts(id) U pts(ptd)
83
- virtual inline bool unionPts(NodeID id, NodeID ptd)
82
+ virtual inline bool unionPts(NodeID id, NodeID ptd) override
84
83
  {
85
84
  id = getEC(id);
86
85
  ptd = getEC(ptd);
@@ -98,6 +97,11 @@ public:
98
97
  else
99
98
  return it->second;
100
99
  }
100
+ /// Return getEC(id)
101
+ inline NodeID sccRepNode(NodeID id) const override
102
+ {
103
+ return getEC(id);
104
+ }
101
105
  void setEC(NodeID node, NodeID rep);
102
106
 
103
107
  inline Set<NodeID>& getSubNodes(NodeID id)
@@ -111,25 +115,11 @@ public:
111
115
  }
112
116
 
113
117
  /// Add copy edge on constraint graph
114
- virtual inline bool addCopyEdge(NodeID src, NodeID dst)
118
+ virtual inline bool addCopyEdge(NodeID src, NodeID dst) override
115
119
  {
116
120
  return consCG->addCopyCGEdge(src, dst);
117
121
  }
118
122
 
119
- protected:
120
- CallSite2DummyValPN
121
- callsite2DummyValPN; ///< Map an instruction to a dummy obj which
122
- ///< created at an indirect callsite, which invokes
123
- ///< a heap allocator
124
- void heapAllocatorViaIndCall(const CallICFGNode* cs, NodePairSet& cpySrcNodes);
125
-
126
- /// Update call graph for the input indirect callsites
127
- virtual bool updateCallGraph(const CallSiteToFunPtrMap& callsites);
128
-
129
- /// Connect formal and actual parameters for indirect callsites
130
- void connectCaller2CalleeParams(const CallICFGNode* cs, const SVFFunction* F,
131
- NodePairSet& cpySrcNodes);
132
-
133
123
  private:
134
124
  static Steensgaard* steens; // static instance
135
125
  NodeToEquivClassMap nodeToECMap;
@@ -51,13 +51,20 @@ public:
51
51
  }
52
52
 
53
53
  /// Type analysis
54
- void analyze();
54
+ void analyze() override;
55
55
 
56
56
  /// Initialize analysis
57
- void initialize();
57
+ void initialize() override;
58
58
 
59
59
  /// Finalize analysis
60
- virtual inline void finalize();
60
+ virtual inline void finalize() override;
61
+
62
+ /// Add copy edge on constraint graph
63
+ inline bool addCopyEdge(NodeID src, NodeID dst) override
64
+ {
65
+ assert(false && "this function should never be executed!");
66
+ return false;
67
+ }
61
68
 
62
69
  /// Resolve callgraph based on CHA
63
70
  void callGraphSolveBasedOnCHA(const CallSiteToFunPtrMap& callsites, CallEdgeMap& newEdges);
@@ -30,6 +30,8 @@
30
30
  #include "SVFIR/SVFModule.h"
31
31
  #include "Graphs/ThreadCallGraph.h"
32
32
  #include "Util/ThreadAPI.h"
33
+ #include "SVFIR/SVFIR.h"
34
+ #include "MemoryModel/PointerAnalysisImpl.h"
33
35
 
34
36
  using namespace SVF;
35
37
  using namespace SVFUtil;
@@ -119,7 +121,7 @@ void ThreadCallGraph::updateJoinEdge(PointerAnalysis* pta)
119
121
  /*!
120
122
  * Add direct fork edges
121
123
  */
122
- void ThreadCallGraph::addDirectForkEdge(const CallICFGNode* cs)
124
+ bool ThreadCallGraph::addDirectForkEdge(const CallICFGNode* cs)
123
125
  {
124
126
 
125
127
  CallGraphNode* caller = getCallGraphNode(cs->getCaller());
@@ -137,13 +139,16 @@ void ThreadCallGraph::addDirectForkEdge(const CallICFGNode* cs)
137
139
 
138
140
  addEdge(edge);
139
141
  addThreadForkEdgeSetMap(cs, edge);
142
+ return true;
140
143
  }
144
+ else
145
+ return false;
141
146
  }
142
147
 
143
148
  /*!
144
149
  * Add indirect fork edge to update call graph
145
150
  */
146
- void ThreadCallGraph::addIndirectForkEdge(const CallICFGNode* cs, const SVFFunction* calleefun)
151
+ bool ThreadCallGraph::addIndirectForkEdge(const CallICFGNode* cs, const SVFFunction* calleefun)
147
152
  {
148
153
  CallGraphNode* caller = getCallGraphNode(cs->getCaller());
149
154
  CallGraphNode* callee = getCallGraphNode(calleefun);
@@ -159,7 +164,10 @@ void ThreadCallGraph::addIndirectForkEdge(const CallICFGNode* cs, const SVFFunct
159
164
 
160
165
  addEdge(edge);
161
166
  addThreadForkEdgeSetMap(cs, edge);
167
+ return true;
162
168
  }
169
+ else
170
+ return false;
163
171
  }
164
172
 
165
173
  /*!
@@ -507,6 +507,43 @@ void BVDataPTAImpl::onTheFlyCallGraphSolve(const CallSiteToFunPtrMap& callsites,
507
507
  }
508
508
  }
509
509
 
510
+ /*!
511
+ * On the fly call graph construction respecting forksite
512
+ * callsites is candidate indirect callsites need to be analyzed based on points-to results
513
+ * newEdges is the new indirect call edges discovered
514
+ */
515
+ void BVDataPTAImpl::onTheFlyThreadCallGraphSolve(const CallSiteToFunPtrMap& callsites,
516
+ CallEdgeMap& newForkEdges)
517
+ {
518
+ // add indirect fork edges
519
+ if(ThreadCallGraph *tdCallGraph = SVFUtil::dyn_cast<ThreadCallGraph>(callgraph))
520
+ {
521
+ for(CallSiteSet::const_iterator it = tdCallGraph->forksitesBegin(),
522
+ eit = tdCallGraph->forksitesEnd(); it != eit; ++it)
523
+ {
524
+ const SVFValue* forkedVal =tdCallGraph->getThreadAPI()->getForkedFun(*it);
525
+ if(SVFUtil::dyn_cast<SVFFunction>(forkedVal) == nullptr)
526
+ {
527
+ SVFIR *pag = this->getPAG();
528
+ const NodeBS targets = this->getPts(pag->getValueNode(forkedVal)).toNodeBS();
529
+ for(NodeBS::iterator ii = targets.begin(), ie = targets.end(); ii != ie; ++ii)
530
+ {
531
+ if(ObjVar *objPN = SVFUtil::dyn_cast<ObjVar>(pag->getGNode(*ii)))
532
+ {
533
+ const MemObj *obj = pag->getObject(objPN);
534
+ if(obj->isFunction())
535
+ {
536
+ const SVFFunction *svfForkedFun = SVFUtil::cast<SVFFunction>(obj->getValue());
537
+ if(tdCallGraph->addIndirectForkEdge(*it, svfForkedFun))
538
+ newForkEdges[*it].insert(svfForkedFun);
539
+ }
540
+ }
541
+ }
542
+ }
543
+ }
544
+ }
545
+ }
546
+
510
547
  /*!
511
548
  * Normalize points-to information for field-sensitive analysis
512
549
  */
@@ -172,12 +172,22 @@ const SVFValue* ThreadAPI::getForkedFun(const CallICFGNode *inst) const
172
172
  return inst->getArgument(2);
173
173
  }
174
174
 
175
- /// Return the forth argument of the call,
176
- /// Note that, it is the sole argument of start routine ( a void* pointer )
177
- const SVFValue* ThreadAPI::getActualParmAtForkSite(const CallICFGNode *inst) const
175
+ const SVFVar* ThreadAPI::getActualParmAtForkSite(const CallICFGNode* inst) const
178
176
  {
179
- assert(isTDFork(inst) && "not a thread fork function!");
180
- return inst->getArgument(3);
177
+ assert(PAG::getPAG()->hasCallSiteArgsMap(inst) && "forksite has no args list!");
178
+ const SVFIR::SVFVarList& csArgList = PAG::getPAG()->getCallSiteArgsList(inst);
179
+ // pthread_create has 4 parameters
180
+ assert(csArgList.size() == 4 && "num of forksite args is not 4");
181
+ return csArgList[3];
182
+ }
183
+
184
+ const SVFVar* ThreadAPI::getFormalParmOfForkedFun(const SVFFunction* F) const
185
+ {
186
+ assert(PAG::getPAG()->hasFunArgsList(F) && "forked function has no args list!");
187
+ const SVFIR::SVFVarList& funArgList = PAG::getPAG()->getFunArgsList(F);
188
+ // in pthread, forked functions are of type void *()(void *args)
189
+ assert(funArgList.size() == 1 && "num of pthread forked function args is not 1!");
190
+ return funArgList[0];
181
191
  }
182
192
 
183
193
  const SVFValue* ThreadAPI::getRetParmAtJoinedSite(const CallICFGNode *inst) const
@@ -187,6 +187,211 @@ void AndersenBase::cleanConsCG(NodeID id)
187
187
  assert(!consCG->hasGNode(id) && "this is either a rep nodeid or a sub nodeid should have already been merged to its field-insensitive base! ");
188
188
  }
189
189
 
190
+ bool AndersenBase::updateCallGraph(const CallSiteToFunPtrMap& callsites)
191
+ {
192
+
193
+ double cgUpdateStart = stat->getClk();
194
+
195
+ CallEdgeMap newEdges;
196
+ onTheFlyCallGraphSolve(callsites, newEdges);
197
+ NodePairSet cpySrcNodes; /// nodes as a src of a generated new copy edge
198
+ for (CallEdgeMap::iterator it = newEdges.begin(), eit = newEdges.end();
199
+ it != eit; ++it)
200
+ {
201
+ for (FunctionSet::iterator cit = it->second.begin(),
202
+ ecit = it->second.end();
203
+ cit != ecit; ++cit)
204
+ {
205
+ connectCaller2CalleeParams(it->first, *cit, cpySrcNodes);
206
+ }
207
+ }
208
+
209
+ bool hasNewForkEdges = updateThreadCallGraph(callsites, cpySrcNodes);
210
+
211
+ for (NodePairSet::iterator it = cpySrcNodes.begin(),
212
+ eit = cpySrcNodes.end();
213
+ it != eit; ++it)
214
+ {
215
+ pushIntoWorklist(it->first);
216
+ }
217
+
218
+ double cgUpdateEnd = stat->getClk();
219
+ timeOfUpdateCallGraph += (cgUpdateEnd - cgUpdateStart) / TIMEINTERVAL;
220
+
221
+ return ((!newEdges.empty()) || hasNewForkEdges);
222
+ }
223
+
224
+ bool AndersenBase::updateThreadCallGraph(const CallSiteToFunPtrMap& callsites,
225
+ NodePairSet& cpySrcNodes)
226
+ {
227
+ CallEdgeMap newForkEdges;
228
+ onTheFlyThreadCallGraphSolve(callsites, newForkEdges);
229
+ for (CallEdgeMap::iterator it = newForkEdges.begin(), eit = newForkEdges.end(); it != eit; it++)
230
+ {
231
+ for (FunctionSet::iterator cit = it->second.begin(),
232
+ ecit = it->second.end();
233
+ cit != ecit; ++cit)
234
+ {
235
+ connectCaller2ForkedFunParams(it->first, *cit, cpySrcNodes);
236
+ }
237
+ }
238
+ return !newForkEdges.empty();
239
+ }
240
+
241
+ /*!
242
+ * Connect formal and actual parameters for indirect forksites
243
+ */
244
+ void AndersenBase::connectCaller2ForkedFunParams(const CallICFGNode* cs, const SVFFunction* F,
245
+ NodePairSet& cpySrcNodes)
246
+ {
247
+ assert(F);
248
+
249
+ DBOUT(DAndersen, outs() << "connect parameters from indirect forksite "
250
+ << cs.getInstruction()->toString() << " to forked function "
251
+ << *F << "\n");
252
+
253
+ ThreadCallGraph *tdCallGraph = SVFUtil::dyn_cast<ThreadCallGraph>(callgraph);
254
+
255
+ const PAGNode *cs_arg = tdCallGraph->getThreadAPI()->getActualParmAtForkSite(cs);
256
+ const PAGNode *fun_arg = tdCallGraph->getThreadAPI()->getFormalParmOfForkedFun(F);
257
+
258
+ if(cs_arg->isPointer() && fun_arg->isPointer())
259
+ {
260
+ DBOUT(DAndersen, outs() << "process actual parm"
261
+ << cs_arg->toString() << "\n");
262
+ NodeID srcAA = sccRepNode(cs_arg->getId());
263
+ NodeID dstFA = sccRepNode(fun_arg->getId());
264
+ if (addCopyEdge(srcAA, dstFA))
265
+ {
266
+ cpySrcNodes.insert(std::make_pair(srcAA, dstFA));
267
+ }
268
+ }
269
+ }
270
+
271
+ ///*!
272
+ // * Connect formal and actual parameters for indirect callsites
273
+ // */
274
+ void AndersenBase::connectCaller2CalleeParams(const CallICFGNode* cs,
275
+ const SVFFunction* F, NodePairSet &cpySrcNodes)
276
+ {
277
+ assert(F);
278
+
279
+ DBOUT(DAndersen, outs() << "connect parameters from indirect callsite " <<
280
+ cs.getInstruction()->toString() << " to callee " << *F << "\n");
281
+
282
+ const CallICFGNode* callBlockNode = cs;
283
+ const RetICFGNode* retBlockNode = cs->getRetICFGNode();
284
+
285
+ if(SVFUtil::isHeapAllocExtFunViaRet(F) && pag->callsiteHasRet(retBlockNode))
286
+ {
287
+ heapAllocatorViaIndCall(cs,cpySrcNodes);
288
+ }
289
+
290
+ if (pag->funHasRet(F) && pag->callsiteHasRet(retBlockNode))
291
+ {
292
+ const PAGNode* cs_return = pag->getCallSiteRet(retBlockNode);
293
+ const PAGNode* fun_return = pag->getFunRet(F);
294
+ if (cs_return->isPointer() && fun_return->isPointer())
295
+ {
296
+ NodeID dstrec = sccRepNode(cs_return->getId());
297
+ NodeID srcret = sccRepNode(fun_return->getId());
298
+ if(addCopyEdge(srcret, dstrec))
299
+ {
300
+ cpySrcNodes.insert(std::make_pair(srcret,dstrec));
301
+ }
302
+ }
303
+ else
304
+ {
305
+ DBOUT(DAndersen, outs() << "not a pointer ignored\n");
306
+ }
307
+ }
308
+
309
+ if (pag->hasCallSiteArgsMap(callBlockNode) && pag->hasFunArgsList(F))
310
+ {
311
+
312
+ // connect actual and formal param
313
+ const SVFIR::SVFVarList& csArgList = pag->getCallSiteArgsList(callBlockNode);
314
+ const SVFIR::SVFVarList& funArgList = pag->getFunArgsList(F);
315
+ //Go through the fixed parameters.
316
+ DBOUT(DPAGBuild, outs() << " args:");
317
+ SVFIR::SVFVarList::const_iterator funArgIt = funArgList.begin(), funArgEit = funArgList.end();
318
+ SVFIR::SVFVarList::const_iterator csArgIt = csArgList.begin(), csArgEit = csArgList.end();
319
+ for (; funArgIt != funArgEit; ++csArgIt, ++funArgIt)
320
+ {
321
+ //Some programs (e.g. Linux kernel) leave unneeded parameters empty.
322
+ if (csArgIt == csArgEit)
323
+ {
324
+ DBOUT(DAndersen, outs() << " !! not enough args\n");
325
+ break;
326
+ }
327
+ const PAGNode *cs_arg = *csArgIt ;
328
+ const PAGNode *fun_arg = *funArgIt;
329
+
330
+ if (cs_arg->isPointer() && fun_arg->isPointer())
331
+ {
332
+ DBOUT(DAndersen, outs() << "process actual parm " << cs_arg->toString() << " \n");
333
+ NodeID srcAA = sccRepNode(cs_arg->getId());
334
+ NodeID dstFA = sccRepNode(fun_arg->getId());
335
+ if(addCopyEdge(srcAA, dstFA))
336
+ {
337
+ cpySrcNodes.insert(std::make_pair(srcAA,dstFA));
338
+ }
339
+ }
340
+ }
341
+
342
+ //Any remaining actual args must be varargs.
343
+ if (F->isVarArg())
344
+ {
345
+ NodeID vaF = sccRepNode(pag->getVarargNode(F));
346
+ DBOUT(DPAGBuild, outs() << "\n varargs:");
347
+ for (; csArgIt != csArgEit; ++csArgIt)
348
+ {
349
+ const PAGNode *cs_arg = *csArgIt;
350
+ if (cs_arg->isPointer())
351
+ {
352
+ NodeID vnAA = sccRepNode(cs_arg->getId());
353
+ if (addCopyEdge(vnAA,vaF))
354
+ {
355
+ cpySrcNodes.insert(std::make_pair(vnAA,vaF));
356
+ }
357
+ }
358
+ }
359
+ }
360
+ if(csArgIt != csArgEit)
361
+ {
362
+ writeWrnMsg("too many args to non-vararg func.");
363
+ writeWrnMsg("(" + cs->getSourceLoc() + ")");
364
+ }
365
+ }
366
+ }
367
+
368
+ void AndersenBase::heapAllocatorViaIndCall(const CallICFGNode* cs, NodePairSet &cpySrcNodes)
369
+ {
370
+ assert(cs->getCalledFunction() == nullptr && "not an indirect callsite?");
371
+ const RetICFGNode* retBlockNode = cs->getRetICFGNode();
372
+ const PAGNode* cs_return = pag->getCallSiteRet(retBlockNode);
373
+ NodeID srcret;
374
+ CallSite2DummyValPN::const_iterator it = callsite2DummyValPN.find(cs);
375
+ if(it != callsite2DummyValPN.end())
376
+ {
377
+ srcret = sccRepNode(it->second);
378
+ }
379
+ else
380
+ {
381
+ NodeID valNode = pag->addDummyValNode();
382
+ NodeID objNode = pag->addDummyObjNode(cs->getCallSite()->getType());
383
+ addPts(valNode,objNode);
384
+ callsite2DummyValPN.insert(std::make_pair(cs,valNode));
385
+ consCG->addConstraintNode(new ConstraintNode(valNode),valNode);
386
+ consCG->addConstraintNode(new ConstraintNode(objNode),objNode);
387
+ srcret = valNode;
388
+ }
389
+
390
+ NodeID dstrec = sccRepNode(cs_return->getId());
391
+ if(addCopyEdge(srcret, dstrec))
392
+ cpySrcNodes.insert(std::make_pair(srcret,dstrec));
393
+ }
394
+
190
395
  void AndersenBase::normalizePointsTo()
191
396
  {
192
397
  SVFIR::MemObjToFieldsMap &memToFieldsMap = pag->getMemToFieldsMap();
@@ -648,157 +853,6 @@ NodeStack& Andersen::SCCDetect()
648
853
  return getSCCDetector()->topoNodeStack();
649
854
  }
650
855
 
651
- /*!
652
- * Update call graph for the input indirect callsites
653
- */
654
- bool Andersen::updateCallGraph(const CallSiteToFunPtrMap& callsites)
655
- {
656
-
657
- double cgUpdateStart = stat->getClk();
658
-
659
- CallEdgeMap newEdges;
660
- onTheFlyCallGraphSolve(callsites,newEdges);
661
- NodePairSet cpySrcNodes; /// nodes as a src of a generated new copy edge
662
- for(CallEdgeMap::iterator it = newEdges.begin(), eit = newEdges.end(); it!=eit; ++it )
663
- {
664
- for(FunctionSet::iterator cit = it->second.begin(), ecit = it->second.end(); cit!=ecit; ++cit)
665
- {
666
- connectCaller2CalleeParams(it->first,*cit,cpySrcNodes);
667
- }
668
- }
669
- for(NodePairSet::iterator it = cpySrcNodes.begin(), eit = cpySrcNodes.end(); it!=eit; ++it)
670
- {
671
- pushIntoWorklist(it->first);
672
- }
673
-
674
- double cgUpdateEnd = stat->getClk();
675
- timeOfUpdateCallGraph += (cgUpdateEnd - cgUpdateStart) / TIMEINTERVAL;
676
-
677
- return (!newEdges.empty());
678
- }
679
-
680
- void Andersen::heapAllocatorViaIndCall(const CallICFGNode* cs, NodePairSet &cpySrcNodes)
681
- {
682
- assert(cs->getCalledFunction() == nullptr && "not an indirect callsite?");
683
- const RetICFGNode* retBlockNode = cs->getRetICFGNode();
684
- const PAGNode* cs_return = pag->getCallSiteRet(retBlockNode);
685
- NodeID srcret;
686
- CallSite2DummyValPN::const_iterator it = callsite2DummyValPN.find(cs);
687
- if(it != callsite2DummyValPN.end())
688
- {
689
- srcret = sccRepNode(it->second);
690
- }
691
- else
692
- {
693
- NodeID valNode = pag->addDummyValNode();
694
- NodeID objNode = pag->addDummyObjNode(cs->getCallSite()->getType());
695
- addPts(valNode,objNode);
696
- callsite2DummyValPN.insert(std::make_pair(cs,valNode));
697
- consCG->addConstraintNode(new ConstraintNode(valNode),valNode);
698
- consCG->addConstraintNode(new ConstraintNode(objNode),objNode);
699
- srcret = valNode;
700
- }
701
-
702
- NodeID dstrec = sccRepNode(cs_return->getId());
703
- if(addCopyEdge(srcret, dstrec))
704
- cpySrcNodes.insert(std::make_pair(srcret,dstrec));
705
- }
706
-
707
- /*!
708
- * Connect formal and actual parameters for indirect callsites
709
- */
710
- void Andersen::connectCaller2CalleeParams(const CallICFGNode* cs, const SVFFunction* F, NodePairSet &cpySrcNodes)
711
- {
712
- assert(F);
713
-
714
- DBOUT(DAndersen, outs() << "connect parameters from indirect callsite " << cs.getInstruction()->toString() << " to callee " << *F << "\n");
715
-
716
- const CallICFGNode* callBlockNode = cs;
717
- const RetICFGNode* retBlockNode = cs->getRetICFGNode();
718
-
719
- if(SVFUtil::isHeapAllocExtFunViaRet(F) && pag->callsiteHasRet(retBlockNode))
720
- {
721
- heapAllocatorViaIndCall(cs,cpySrcNodes);
722
- }
723
-
724
- if (pag->funHasRet(F) && pag->callsiteHasRet(retBlockNode))
725
- {
726
- const PAGNode* cs_return = pag->getCallSiteRet(retBlockNode);
727
- const PAGNode* fun_return = pag->getFunRet(F);
728
- if (cs_return->isPointer() && fun_return->isPointer())
729
- {
730
- NodeID dstrec = sccRepNode(cs_return->getId());
731
- NodeID srcret = sccRepNode(fun_return->getId());
732
- if(addCopyEdge(srcret, dstrec))
733
- {
734
- cpySrcNodes.insert(std::make_pair(srcret,dstrec));
735
- }
736
- }
737
- else
738
- {
739
- DBOUT(DAndersen, outs() << "not a pointer ignored\n");
740
- }
741
- }
742
-
743
- if (pag->hasCallSiteArgsMap(callBlockNode) && pag->hasFunArgsList(F))
744
- {
745
-
746
- // connect actual and formal param
747
- const SVFIR::SVFVarList& csArgList = pag->getCallSiteArgsList(callBlockNode);
748
- const SVFIR::SVFVarList& funArgList = pag->getFunArgsList(F);
749
- //Go through the fixed parameters.
750
- DBOUT(DPAGBuild, outs() << " args:");
751
- SVFIR::SVFVarList::const_iterator funArgIt = funArgList.begin(), funArgEit = funArgList.end();
752
- SVFIR::SVFVarList::const_iterator csArgIt = csArgList.begin(), csArgEit = csArgList.end();
753
- for (; funArgIt != funArgEit; ++csArgIt, ++funArgIt)
754
- {
755
- //Some programs (e.g. Linux kernel) leave unneeded parameters empty.
756
- if (csArgIt == csArgEit)
757
- {
758
- DBOUT(DAndersen, outs() << " !! not enough args\n");
759
- break;
760
- }
761
- const PAGNode *cs_arg = *csArgIt ;
762
- const PAGNode *fun_arg = *funArgIt;
763
-
764
- if (cs_arg->isPointer() && fun_arg->isPointer())
765
- {
766
- DBOUT(DAndersen, outs() << "process actual parm " << cs_arg->toString() << " \n");
767
- NodeID srcAA = sccRepNode(cs_arg->getId());
768
- NodeID dstFA = sccRepNode(fun_arg->getId());
769
- if(addCopyEdge(srcAA, dstFA))
770
- {
771
- cpySrcNodes.insert(std::make_pair(srcAA,dstFA));
772
- }
773
- }
774
- }
775
-
776
- //Any remaining actual args must be varargs.
777
- if (F->isVarArg())
778
- {
779
- NodeID vaF = sccRepNode(pag->getVarargNode(F));
780
- DBOUT(DPAGBuild, outs() << "\n varargs:");
781
- for (; csArgIt != csArgEit; ++csArgIt)
782
- {
783
- const PAGNode *cs_arg = *csArgIt;
784
- if (cs_arg->isPointer())
785
- {
786
- NodeID vnAA = sccRepNode(cs_arg->getId());
787
- if (addCopyEdge(vnAA,vaF))
788
- {
789
- cpySrcNodes.insert(std::make_pair(vnAA,vaF));
790
- }
791
- }
792
- }
793
- }
794
- if(csArgIt != csArgEit)
795
- {
796
- writeWrnMsg("too many args to non-vararg func.");
797
- writeWrnMsg("(" + cs->getSourceLoc() + ")");
798
- }
799
- }
800
- }
801
-
802
856
  /*!
803
857
  * merge nodeId to newRepId. Return true if the newRepId is a PWC node
804
858
  */
@@ -122,166 +122,4 @@ void Steensgaard::processAllAddr()
122
122
  pushIntoWorklist(dst);
123
123
  }
124
124
  }
125
- }
126
-
127
- bool Steensgaard::updateCallGraph(const CallSiteToFunPtrMap& callsites)
128
- {
129
-
130
- double cgUpdateStart = stat->getClk();
131
-
132
- CallEdgeMap newEdges;
133
- onTheFlyCallGraphSolve(callsites, newEdges);
134
- NodePairSet cpySrcNodes; /// nodes as a src of a generated new copy edge
135
- for (CallEdgeMap::iterator it = newEdges.begin(), eit = newEdges.end();
136
- it != eit; ++it)
137
- {
138
- for (FunctionSet::iterator cit = it->second.begin(),
139
- ecit = it->second.end();
140
- cit != ecit; ++cit)
141
- {
142
- connectCaller2CalleeParams(it->first, *cit, cpySrcNodes);
143
- }
144
- }
145
- for (NodePairSet::iterator it = cpySrcNodes.begin(),
146
- eit = cpySrcNodes.end();
147
- it != eit; ++it)
148
- {
149
- pushIntoWorklist(it->first);
150
- }
151
-
152
- double cgUpdateEnd = stat->getClk();
153
- timeOfUpdateCallGraph += (cgUpdateEnd - cgUpdateStart) / TIMEINTERVAL;
154
-
155
- return (!newEdges.empty());
156
- }
157
-
158
- void Steensgaard::heapAllocatorViaIndCall(const CallICFGNode* cs, NodePairSet& cpySrcNodes)
159
- {
160
- assert(cs->getCalledFunction() == nullptr && "not an indirect callsite?");
161
- const RetICFGNode* retBlockNode = cs->getRetICFGNode();
162
- const PAGNode* cs_return = pag->getCallSiteRet(retBlockNode);
163
- NodeID srcret;
164
- CallSite2DummyValPN::const_iterator it = callsite2DummyValPN.find(cs);
165
- if (it != callsite2DummyValPN.end())
166
- {
167
- srcret = getEC(it->second);
168
- }
169
- else
170
- {
171
- NodeID valNode = pag->addDummyValNode();
172
- NodeID objNode = pag->addDummyObjNode(cs->getCallSite()->getType());
173
- addPts(valNode, objNode);
174
- callsite2DummyValPN.insert(std::make_pair(cs, valNode));
175
- consCG->addConstraintNode(new ConstraintNode(valNode), valNode);
176
- consCG->addConstraintNode(new ConstraintNode(objNode), objNode);
177
- srcret = valNode;
178
- }
179
-
180
- NodeID dstrec = getEC(cs_return->getId());
181
- if (addCopyEdge(srcret, dstrec))
182
- cpySrcNodes.insert(std::make_pair(srcret, dstrec));
183
- }
184
-
185
- /*!
186
- * Connect formal and actual parameters for indirect callsites
187
- */
188
- void Steensgaard::connectCaller2CalleeParams(const CallICFGNode* cs, const SVFFunction* F,
189
- NodePairSet& cpySrcNodes)
190
- {
191
- assert(F);
192
-
193
- DBOUT(DAndersen, outs() << "connect parameters from indirect callsite "
194
- << cs.getInstruction()->toString() << " to callee "
195
- << *F << "\n");
196
-
197
- const CallICFGNode* callBlockNode = cs;
198
- const RetICFGNode* retBlockNode = cs->getRetICFGNode();
199
-
200
- if (SVFUtil::isHeapAllocExtFunViaRet(F) &&
201
- pag->callsiteHasRet(retBlockNode))
202
- {
203
- heapAllocatorViaIndCall(cs, cpySrcNodes);
204
- }
205
-
206
- if (pag->funHasRet(F) && pag->callsiteHasRet(retBlockNode))
207
- {
208
- const PAGNode* cs_return = pag->getCallSiteRet(retBlockNode);
209
- const PAGNode* fun_return = pag->getFunRet(F);
210
- if (cs_return->isPointer() && fun_return->isPointer())
211
- {
212
- NodeID dstrec = getEC(cs_return->getId());
213
- NodeID srcret = getEC(fun_return->getId());
214
- if (addCopyEdge(srcret, dstrec))
215
- {
216
- cpySrcNodes.insert(std::make_pair(srcret, dstrec));
217
- }
218
- }
219
- else
220
- {
221
- DBOUT(DAndersen, outs() << "not a pointer ignored\n");
222
- }
223
- }
224
-
225
- if (pag->hasCallSiteArgsMap(callBlockNode) && pag->hasFunArgsList(F))
226
- {
227
-
228
- // connect actual and formal param
229
- const SVFIR::SVFVarList& csArgList =
230
- pag->getCallSiteArgsList(callBlockNode);
231
- const SVFIR::SVFVarList& funArgList = pag->getFunArgsList(F);
232
- // Go through the fixed parameters.
233
- DBOUT(DPAGBuild, outs() << " args:");
234
- SVFIR::SVFVarList::const_iterator funArgIt = funArgList.begin(),
235
- funArgEit = funArgList.end();
236
- SVFIR::SVFVarList::const_iterator csArgIt = csArgList.begin(),
237
- csArgEit = csArgList.end();
238
- for (; funArgIt != funArgEit; ++csArgIt, ++funArgIt)
239
- {
240
- // Some programs (e.g. Linux kernel) leave unneeded parameters
241
- // empty.
242
- if (csArgIt == csArgEit)
243
- {
244
- DBOUT(DAndersen, outs() << " !! not enough args\n");
245
- break;
246
- }
247
- const PAGNode* cs_arg = *csArgIt;
248
- const PAGNode* fun_arg = *funArgIt;
249
-
250
- if (cs_arg->isPointer() && fun_arg->isPointer())
251
- {
252
- DBOUT(DAndersen, outs() << "process actual parm "
253
- << cs_arg->toString() << " \n");
254
- NodeID srcAA = getEC(cs_arg->getId());
255
- NodeID dstFA = getEC(fun_arg->getId());
256
- if (addCopyEdge(srcAA, dstFA))
257
- {
258
- cpySrcNodes.insert(std::make_pair(srcAA, dstFA));
259
- }
260
- }
261
- }
262
-
263
- // Any remaining actual args must be varargs.
264
- if (F->isVarArg())
265
- {
266
- NodeID vaF = getEC(pag->getVarargNode(F));
267
- DBOUT(DPAGBuild, outs() << "\n varargs:");
268
- for (; csArgIt != csArgEit; ++csArgIt)
269
- {
270
- const PAGNode* cs_arg = *csArgIt;
271
- if (cs_arg->isPointer())
272
- {
273
- NodeID vnAA = getEC(cs_arg->getId());
274
- if (addCopyEdge(vnAA, vaF))
275
- {
276
- cpySrcNodes.insert(std::make_pair(vnAA, vaF));
277
- }
278
- }
279
- }
280
- }
281
- if (csArgIt != csArgEit)
282
- {
283
- writeWrnMsg("too many args to non-vararg func.");
284
- writeWrnMsg("(" + cs->getSourceLoc() + ")");
285
- }
286
- }
287
- }
125
+ }
@@ -259,7 +259,7 @@ void SVFIRBuilder::handleExtCall(const CallBase* cs, const SVFFunction* svfCalle
259
259
  if (const SVFFunction* forkedFun = SVFUtil::dyn_cast<SVFFunction>(getForkedFun(callICFGNode)))
260
260
  {
261
261
  forkedFun = forkedFun->getDefFunForMultipleModule();
262
- const SVFValue* actualParm = getActualParmAtForkSite(callICFGNode);
262
+ const SVFVar* actualParm = getActualParmAtForkSite(callICFGNode);
263
263
  /// pthread_create has 1 arg.
264
264
  /// apr_thread_create has 2 arg.
265
265
  assert((forkedFun->arg_size() <= 2) && "Size of formal parameter of start routine should be one");
@@ -267,10 +267,10 @@ void SVFIRBuilder::handleExtCall(const CallBase* cs, const SVFFunction* svfCalle
267
267
  {
268
268
  const SVFArgument* formalParm = forkedFun->getArg(0);
269
269
  /// Connect actual parameter to formal parameter of the start routine
270
- if (actualParm->getType()->isPointerTy() && formalParm->getType()->isPointerTy())
270
+ if (actualParm->isPointer() && formalParm->getType()->isPointerTy())
271
271
  {
272
272
  FunEntryICFGNode *entry = pag->getICFG()->getFunEntryICFGNode(forkedFun);
273
- addThreadForkEdge(pag->getValueNode(actualParm), pag->getValueNode(formalParm), callICFGNode, entry);
273
+ addThreadForkEdge(actualParm->getId(), pag->getValueNode(formalParm), callICFGNode, entry);
274
274
  }
275
275
  }
276
276
  }