svf-tools 1.0.1231 → 1.0.1233

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.1231",
3
+ "version": "1.0.1233",
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": {
@@ -597,13 +597,11 @@ protected:
597
597
  /// do not set def here, this node is not a variable definition
598
598
  }
599
599
  /// Add a formal parameter VFG node
600
- inline void addFormalParmVFGNode(const ValVar* fparm, const FunObjVar* fun, CallPESet& callPEs)
600
+ inline void addFormalParmVFGNode(const ValVar* fparm, const FunObjVar* fun, const CallPE* callPE)
601
601
  {
602
602
  FormalParmVFGNode* sNode = new FormalParmVFGNode(totalVFGNode++,fparm,fun);
603
603
  addVFGNode(sNode, pag->getICFG()->getFunEntryICFGNode(fun));
604
- for(CallPESet::const_iterator it = callPEs.begin(), eit=callPEs.end();
605
- it!=eit; ++it)
606
- sNode->addCallPE(*it);
604
+ sNode->setCallPE(callPE);
607
605
 
608
606
  setDef(fparm,sNode);
609
607
  SVFVarToFormalParmMap[fparm] = sNode;
@@ -1028,12 +1028,12 @@ class FormalParmVFGNode : public ArgumentVFGNode
1028
1028
  {
1029
1029
  private:
1030
1030
  const FunObjVar* fun;
1031
- CallPESet callPEs;
1031
+ const CallPE* callPE;
1032
1032
 
1033
1033
  public:
1034
1034
  /// Constructor
1035
1035
  FormalParmVFGNode(NodeID id, const ValVar* n, const FunObjVar* f):
1036
- ArgumentVFGNode(id, n, FParm), fun(f)
1036
+ ArgumentVFGNode(id, n, FParm), fun(f), callPE(nullptr)
1037
1037
  {
1038
1038
  }
1039
1039
 
@@ -1048,20 +1048,15 @@ public:
1048
1048
  {
1049
1049
  return fun;
1050
1050
  }
1051
- /// Return call edge
1052
- inline void addCallPE(const CallPE* call)
1051
+ /// Set the (single, phi-like) CallPE for this formal parameter
1052
+ inline void setCallPE(const CallPE* call)
1053
1053
  {
1054
- callPEs.insert(call);
1054
+ callPE = call;
1055
1055
  }
1056
- /// Call edge iterator
1057
- ///@{
1058
- inline CallPESet::const_iterator callPEBegin() const
1059
- {
1060
- return callPEs.begin();
1061
- }
1062
- inline CallPESet::const_iterator callPEEnd() const
1056
+ /// Return the CallPE (phi-like, merges all actual params)
1057
+ inline const CallPE* getCallPE() const
1063
1058
  {
1064
- return callPEs.end();
1059
+ return callPE;
1065
1060
  }
1066
1061
  //@}
1067
1062
 
@@ -57,6 +57,7 @@ public:
57
57
  typedef std::vector<const SVFStmt*> SVFStmtList;
58
58
  typedef std::vector<const ValVar*> ValVarList;
59
59
  typedef Map<const SVFVar*,PhiStmt*> PHINodeMap;
60
+ typedef Map<const SVFVar*,CallPE*> FParmToCallPEMap;
60
61
  typedef Map<const FunObjVar*,ValVarList> FunToArgsListMap;
61
62
  typedef Map<const CallICFGNode*,ValVarList> CSToArgsListMap;
62
63
  typedef Map<const RetICFGNode*,const ValVar*> CSToRetMap;
@@ -84,6 +85,7 @@ private:
84
85
  MemObjToFieldsMap memToFieldsMap; ///< Map a mem object id to all its fields
85
86
  SVFStmtSet globSVFStmtSet; ///< Global PAGEdges without control flow information
86
87
  PHINodeMap phiNodeMap; ///< A set of phi copy edges
88
+ FParmToCallPEMap fParmToCallPEMap; ///< Map a formal param to its CallPE
87
89
  FunToArgsListMap funArgsListMap; ///< Map a function to a list of all its formal parameters
88
90
  CSToArgsListMap callSiteArgsListMap; ///< Map a callsite to a list of all its actual parameters
89
91
  CSToRetMap callSiteRetMap; ///< Map a callsite to its callsite returns PAGNodes
@@ -353,6 +355,12 @@ public:
353
355
  {
354
356
  return phiNodeMap.find(node) != phiNodeMap.end();
355
357
  }
358
+ /// Get the CallPE for a formal parameter (phi-like, nullptr if not found)
359
+ inline CallPE* getCallPEForFormalParm(const SVFVar* param) const
360
+ {
361
+ auto it = fParmToCallPEMap.find(param);
362
+ return it != fParmToCallPEMap.end() ? it->second : nullptr;
363
+ }
356
364
 
357
365
  /// Function has arguments list
358
366
  inline bool hasFunArgsList(const FunObjVar* func) const
@@ -911,7 +919,7 @@ private:
911
919
  /// Add Store edge
912
920
  StoreStmt* addStoreStmt(NodeID src, NodeID dst, const ICFGNode* val);
913
921
  void addStoreStmt(StoreStmt* edge, SVFVar* src, SVFVar* dst);
914
- /// Add Call edge
922
+ /// Add Call edge (phi-like: merges actual params from all call sites into formal param)
915
923
  CallPE* addCallPE(NodeID src, NodeID dst, const CallICFGNode* cs,
916
924
  const FunEntryICFGNode* entry);
917
925
  void addCallPE(CallPE* edge, SVFVar* src, SVFVar* dst);
@@ -335,10 +335,8 @@ public:
335
335
  edge->getEdgeKind() == SVFStmt::Copy ||
336
336
  edge->getEdgeKind() == SVFStmt::Store ||
337
337
  edge->getEdgeKind() == SVFStmt::Load ||
338
- edge->getEdgeKind() == SVFStmt::Call ||
339
338
  edge->getEdgeKind() == SVFStmt::Ret ||
340
339
  edge->getEdgeKind() == SVFStmt::Gep ||
341
- edge->getEdgeKind() == SVFStmt::ThreadFork ||
342
340
  edge->getEdgeKind() == SVFStmt::ThreadJoin;
343
341
  }
344
342
  static inline bool classof(const GenericPAGEdgeTy* edge)
@@ -347,10 +345,8 @@ public:
347
345
  edge->getEdgeKind() == SVFStmt::Copy ||
348
346
  edge->getEdgeKind() == SVFStmt::Store ||
349
347
  edge->getEdgeKind() == SVFStmt::Load ||
350
- edge->getEdgeKind() == SVFStmt::Call ||
351
348
  edge->getEdgeKind() == SVFStmt::Ret ||
352
349
  edge->getEdgeKind() == SVFStmt::Gep ||
353
- edge->getEdgeKind() == SVFStmt::ThreadFork ||
354
350
  edge->getEdgeKind() == SVFStmt::ThreadJoin;
355
351
  }
356
352
  //@}
@@ -693,67 +689,6 @@ public:
693
689
  };
694
690
 
695
691
 
696
- /*!
697
- * Call
698
- */
699
- class CallPE: public AssignStmt
700
- {
701
- friend class GraphDBClient;
702
-
703
- private:
704
- CallPE(const CallPE&); ///< place holder
705
- void operator=(const CallPE&); ///< place holder
706
-
707
- const CallICFGNode* call; /// the callsite statement calling from
708
- const FunEntryICFGNode* entry; /// the function exit statement calling to
709
-
710
- public:
711
- /// Methods for support type inquiry through isa, cast, and dyn_cast:
712
- //@{
713
- static inline bool classof(const CallPE*)
714
- {
715
- return true;
716
- }
717
- static inline bool classof(const SVFStmt* edge)
718
- {
719
- return edge->getEdgeKind() == SVFStmt::Call ||
720
- edge->getEdgeKind() == SVFStmt::ThreadFork;
721
- }
722
- static inline bool classof(const GenericPAGEdgeTy* edge)
723
- {
724
- return edge->getEdgeKind() == SVFStmt::Call ||
725
- edge->getEdgeKind() == SVFStmt::ThreadFork;
726
- }
727
- //@}
728
-
729
- /// constructor
730
- CallPE(SVFVar* s, SVFVar* d, const CallICFGNode* i,
731
- const FunEntryICFGNode* e, GEdgeKind k = SVFStmt::Call);
732
-
733
- /// Get method for the call instruction
734
- //@{
735
- inline const CallICFGNode* getCallInst() const
736
- {
737
- return call;
738
- }
739
- inline const CallICFGNode* getCallSite() const
740
- {
741
- return call;
742
- }
743
- inline const FunEntryICFGNode* getFunEntryICFGNode() const
744
- {
745
- return entry;
746
- }
747
- //@}
748
-
749
- const ValVar* getRHSVar() const;
750
- const ValVar* getLHSVar() const;
751
- const ValVar* getSrcNode() const;
752
- const ValVar* getDstNode() const;
753
-
754
- virtual const std::string toString() const override;
755
- };
756
-
757
692
  /*!
758
693
  * Return
759
694
  */
@@ -850,12 +785,14 @@ public:
850
785
  static inline bool classof(const SVFStmt* node)
851
786
  {
852
787
  return node->getEdgeKind() == Phi || node->getEdgeKind() == Select ||
853
- node->getEdgeKind() == BinaryOp || node->getEdgeKind() == Cmp;
788
+ node->getEdgeKind() == BinaryOp || node->getEdgeKind() == Cmp ||
789
+ node->getEdgeKind() == Call || node->getEdgeKind() == ThreadFork;
854
790
  }
855
791
  static inline bool classof(const GenericPAGEdgeTy* node)
856
792
  {
857
793
  return node->getEdgeKind() == Phi || node->getEdgeKind() == Select ||
858
- node->getEdgeKind() == BinaryOp || node->getEdgeKind() == Cmp;
794
+ node->getEdgeKind() == BinaryOp || node->getEdgeKind() == Cmp ||
795
+ node->getEdgeKind() == Call || node->getEdgeKind() == ThreadFork;
859
796
  }
860
797
  //@}
861
798
  /// Operands and result at a BinaryNode e.g., p = q + r, `p` is resVar and
@@ -891,6 +828,81 @@ public:
891
828
  //@}
892
829
  };
893
830
 
831
+ /*!
832
+ * Call
833
+ * CallPE is a phi-like statement at function entry that merges actual parameters
834
+ * from all call sites into the formal parameter.
835
+ * e.g., formal_param = CallPE(actual1@callsite1, actual2@callsite2, ...)
836
+ */
837
+ class CallPE: public MultiOpndStmt
838
+ {
839
+ friend class GraphDBClient;
840
+
841
+ public:
842
+ typedef std::vector<const CallICFGNode*> CallICFGNodeVec;
843
+
844
+ private:
845
+ CallPE(const CallPE&); ///< place holder
846
+ void operator=(const CallPE&); ///< place holder
847
+
848
+ CallICFGNodeVec opCallICFGNodes; /// each operand's call site
849
+ const FunEntryICFGNode* entry; /// the function entry node
850
+
851
+ public:
852
+ /// Methods for support type inquiry through isa, cast, and dyn_cast:
853
+ //@{
854
+ static inline bool classof(const CallPE*)
855
+ {
856
+ return true;
857
+ }
858
+ static inline bool classof(const SVFStmt* edge)
859
+ {
860
+ return edge->getEdgeKind() == SVFStmt::Call ||
861
+ edge->getEdgeKind() == SVFStmt::ThreadFork;
862
+ }
863
+ static inline bool classof(const GenericPAGEdgeTy* edge)
864
+ {
865
+ return edge->getEdgeKind() == SVFStmt::Call ||
866
+ edge->getEdgeKind() == SVFStmt::ThreadFork;
867
+ }
868
+ //@}
869
+
870
+ /// constructor
871
+ CallPE(ValVar* res, const OPVars& opnds,
872
+ const CallICFGNodeVec& icfgNodes,
873
+ const FunEntryICFGNode* e,
874
+ GEdgeKind k = SVFStmt::Call);
875
+
876
+ /// Add an operand (actual param) from a call site
877
+ void addOpVar(ValVar* op, const CallICFGNode* call)
878
+ {
879
+ opVars.push_back(op);
880
+ opCallICFGNodes.push_back(call);
881
+ assert(opVars.size() == opCallICFGNodes.size() &&
882
+ "Numbers of operands and their CallICFGNodes are not consistent?");
883
+ }
884
+
885
+ /// Return the CallICFGNode of the i-th operand
886
+ inline const CallICFGNode* getOpCallICFGNode(u32_t op_idx) const
887
+ {
888
+ return opCallICFGNodes.at(op_idx);
889
+ }
890
+
891
+ /// Return all call site ICFGNodes
892
+ inline const CallICFGNodeVec& getOpCallICFGNodes() const
893
+ {
894
+ return opCallICFGNodes;
895
+ }
896
+
897
+ /// Return the function entry node
898
+ inline const FunEntryICFGNode* getFunEntryICFGNode() const
899
+ {
900
+ return entry;
901
+ }
902
+
903
+ virtual const std::string toString() const override;
904
+ };
905
+
894
906
  /*!
895
907
  * Phi statement (e.g., p = phi(q,r) which receives values from variables q and r from different paths)
896
908
  * it is typically at a joint point of the control-flow graph
@@ -1340,17 +1352,13 @@ public:
1340
1352
  //@}
1341
1353
 
1342
1354
  /// constructor
1343
- TDForkPE(SVFVar* s, SVFVar* d, const CallICFGNode* i,
1344
- const FunEntryICFGNode* entry)
1345
- : CallPE(s, d, i, entry, SVFStmt::ThreadFork)
1355
+ TDForkPE(ValVar* res, const OPVars& opnds,
1356
+ const CallICFGNodeVec& icfgNodes,
1357
+ const FunEntryICFGNode* e)
1358
+ : CallPE(res, opnds, icfgNodes, e, SVFStmt::ThreadFork)
1346
1359
  {
1347
1360
  }
1348
1361
 
1349
- const ValVar* getRHSVar() const;
1350
- const ValVar* getLHSVar() const;
1351
- const ValVar* getSrcNode() const;
1352
- const ValVar* getDstNode() const;
1353
-
1354
1362
  virtual const std::string toString() const;
1355
1363
 
1356
1364
  };
@@ -2229,16 +2229,34 @@ class BasicBlockValVar: public ValVar
2229
2229
  friend class GraphDBClient;
2230
2230
 
2231
2231
  public:
2232
- static inline bool classof(const BasicBlockValVar*) { return true; }
2233
- static inline bool classof(const SVFVar* node) { return node->getNodeKind() == SVFVar::BasicBlockValNode; }
2234
- static inline bool classof(const ValVar* node) { return node->getNodeKind() == SVFVar::BasicBlockValNode; }
2235
- static inline bool classof(const GenericPAGNodeTy* node) { return node->getNodeKind() == SVFVar::BasicBlockValNode; }
2236
- static inline bool classof(const SVFValue* node) { return node->getNodeKind() == SVFVar::BasicBlockValNode; }
2232
+ static inline bool classof(const BasicBlockValVar*)
2233
+ {
2234
+ return true;
2235
+ }
2236
+ static inline bool classof(const SVFVar* node)
2237
+ {
2238
+ return node->getNodeKind() == SVFVar::BasicBlockValNode;
2239
+ }
2240
+ static inline bool classof(const ValVar* node)
2241
+ {
2242
+ return node->getNodeKind() == SVFVar::BasicBlockValNode;
2243
+ }
2244
+ static inline bool classof(const GenericPAGNodeTy* node)
2245
+ {
2246
+ return node->getNodeKind() == SVFVar::BasicBlockValNode;
2247
+ }
2248
+ static inline bool classof(const SVFValue* node)
2249
+ {
2250
+ return node->getNodeKind() == SVFVar::BasicBlockValNode;
2251
+ }
2237
2252
 
2238
2253
  BasicBlockValVar(NodeID i, const SVFType* svfType)
2239
2254
  : ValVar(i, svfType, nullptr, BasicBlockValNode) {}
2240
2255
 
2241
- inline const std::string getValueName() const { return "basicBlockVal"; }
2256
+ inline const std::string getValueName() const
2257
+ {
2258
+ return "basicBlockVal";
2259
+ }
2242
2260
  virtual const std::string toString() const;
2243
2261
  };
2244
2262
 
@@ -2253,16 +2271,34 @@ class AsmPCValVar: public ValVar
2253
2271
  friend class GraphDBClient;
2254
2272
 
2255
2273
  public:
2256
- static inline bool classof(const AsmPCValVar*) { return true; }
2257
- static inline bool classof(const SVFVar* node) { return node->getNodeKind() == SVFVar::AsmPCValNode; }
2258
- static inline bool classof(const ValVar* node) { return node->getNodeKind() == SVFVar::AsmPCValNode; }
2259
- static inline bool classof(const GenericPAGNodeTy* node) { return node->getNodeKind() == SVFVar::AsmPCValNode; }
2260
- static inline bool classof(const SVFValue* node) { return node->getNodeKind() == SVFVar::AsmPCValNode; }
2274
+ static inline bool classof(const AsmPCValVar*)
2275
+ {
2276
+ return true;
2277
+ }
2278
+ static inline bool classof(const SVFVar* node)
2279
+ {
2280
+ return node->getNodeKind() == SVFVar::AsmPCValNode;
2281
+ }
2282
+ static inline bool classof(const ValVar* node)
2283
+ {
2284
+ return node->getNodeKind() == SVFVar::AsmPCValNode;
2285
+ }
2286
+ static inline bool classof(const GenericPAGNodeTy* node)
2287
+ {
2288
+ return node->getNodeKind() == SVFVar::AsmPCValNode;
2289
+ }
2290
+ static inline bool classof(const SVFValue* node)
2291
+ {
2292
+ return node->getNodeKind() == SVFVar::AsmPCValNode;
2293
+ }
2261
2294
 
2262
2295
  AsmPCValVar(NodeID i, const SVFType* svfType)
2263
2296
  : ValVar(i, svfType, nullptr, AsmPCValNode) {}
2264
2297
 
2265
- inline const std::string getValueName() const { return "asmPCVal"; }
2298
+ inline const std::string getValueName() const
2299
+ {
2300
+ return "asmPCVal";
2301
+ }
2266
2302
  virtual const std::string toString() const;
2267
2303
  };
2268
2304
 
@@ -1222,12 +1222,24 @@ void AbstractInterpretation::updateStateOnPhi(const PhiStmt *phi)
1222
1222
  }
1223
1223
 
1224
1224
 
1225
+ /// Handle CallPE: phi-like merging of actual parameters from all call sites
1226
+ /// into the formal parameter at FunEntryICFGNode (e.g., formal = join(actual1@cs1, actual2@cs2, ...))
1225
1227
  void AbstractInterpretation::updateStateOnCall(const CallPE *callPE)
1226
1228
  {
1227
1229
  AbstractState& as = getAbstractState(callPE->getICFGNode());
1228
- NodeID lhs = callPE->getLHSVarID();
1229
- NodeID rhs = callPE->getRHSVarID();
1230
- as[lhs] = as[rhs];
1230
+ NodeID res = callPE->getResID();
1231
+ AbstractValue rhs;
1232
+ for (u32_t i = 0; i < callPE->getOpVarNum(); i++)
1233
+ {
1234
+ NodeID curId = callPE->getOpVarID(i);
1235
+ const ICFGNode* opICFGNode = callPE->getOpCallICFGNode(i);
1236
+ if (hasAbstractState(opICFGNode))
1237
+ {
1238
+ AbstractState& opAs = getAbstractState(opICFGNode);
1239
+ rhs.join_with(opAs[curId]);
1240
+ }
1241
+ }
1242
+ as[res] = rhs;
1231
1243
  }
1232
1244
 
1233
1245
  void AbstractInterpretation::updateStateOnRet(const RetPE *retPE)
@@ -86,8 +86,9 @@ void ConstraintGraph::buildCG()
86
86
  for (SVFStmt::SVFStmtSetTy::iterator iter = calls.begin(), eiter =
87
87
  calls.end(); iter != eiter; ++iter)
88
88
  {
89
- const CallPE* edge = SVFUtil::cast<CallPE>(*iter);
90
- addCopyCGEdge(edge->getRHSVarID(),edge->getLHSVarID());
89
+ const CallPE* callPE = SVFUtil::cast<CallPE>(*iter);
90
+ for(u32_t i = 0; i < callPE->getOpVarNum(); i++)
91
+ addCopyCGEdge(callPE->getOpVarID(i), callPE->getResID());
91
92
  }
92
93
 
93
94
  SVFStmt::SVFStmtSetTy& rets = getSVFStmtSet(SVFStmt::Ret);
@@ -102,8 +103,9 @@ void ConstraintGraph::buildCG()
102
103
  for (SVFStmt::SVFStmtSetTy::iterator iter = tdfks.begin(), eiter =
103
104
  tdfks.end(); iter != eiter; ++iter)
104
105
  {
105
- const TDForkPE* edge = SVFUtil::cast<TDForkPE>(*iter);
106
- addCopyCGEdge(edge->getRHSVarID(),edge->getLHSVarID());
106
+ const TDForkPE* forkPE = SVFUtil::cast<TDForkPE>(*iter);
107
+ for(u32_t i = 0; i < forkPE->getOpVarNum(); i++)
108
+ addCopyCGEdge(forkPE->getOpVarID(i), forkPE->getResID());
107
109
  }
108
110
 
109
111
  SVFStmt::SVFStmtSetTy& tdjns = getSVFStmtSet(SVFStmt::ThreadJoin);
@@ -444,17 +444,7 @@ void ICFG::updateCallGraph(CallGraph* callgraph)
444
444
  {
445
445
  FunEntryICFGNode* calleeEntryNode = getFunEntryBlock(callee);
446
446
  FunExitICFGNode* calleeExitNode = getFunExitBlock(callee);
447
- if(ICFGEdge* callEdge = addCallEdge(callBlockNode, calleeEntryNode))
448
- {
449
- for (const SVFStmt *stmt : callBlockNode->getSVFStmts())
450
- {
451
- if(const CallPE *callPE = SVFUtil::dyn_cast<CallPE>(stmt))
452
- {
453
- if(callPE->getFunEntryICFGNode() == calleeEntryNode)
454
- SVFUtil::cast<CallCFGEdge>(callEdge)->addCallPE(callPE);
455
- }
456
- }
457
- }
447
+ addCallEdge(callBlockNode, calleeEntryNode);
458
448
  if(ICFGEdge* retEdge = addRetEdge(calleeExitNode, retBlockNode))
459
449
  {
460
450
  for (const SVFStmt *stmt : retBlockNode->getSVFStmts())
@@ -514,7 +514,7 @@ struct DOTGraphTraits<IRGraph*> : public DefaultDOTGraphTraits
514
514
  assert(edge && "No edge found!!");
515
515
  if(const CallPE* calledge = SVFUtil::dyn_cast<CallPE>(edge))
516
516
  {
517
- return calledge->getCallSite()->getSourceLoc();
517
+ return calledge->getFunEntryICFGNode()->getSourceLoc();
518
518
  }
519
519
  else if(const RetPE* retedge = SVFUtil::dyn_cast<RetPE>(edge))
520
520
  {
@@ -499,7 +499,8 @@ void VFG::addVFGNodes()
499
499
  forks.end(); iter != eiter; ++iter)
500
500
  {
501
501
  TDForkPE* forkedge = SVFUtil::cast<TDForkPE>(*iter);
502
- addActualParmVFGNode(forkedge->getRHSVar(),forkedge->getCallSite());
502
+ for(u32_t i = 0; i < forkedge->getOpVarNum(); i++)
503
+ addActualParmVFGNode(forkedge->getOpVar(i), forkedge->getOpCallICFGNode(i));
503
504
  }
504
505
 
505
506
  // initialize actual parameter nodes
@@ -538,18 +539,8 @@ void VFG::addVFGNodes()
538
539
  if (isInterestedSVFVar(param) == false || hasBlackHoleConstObjAddrAsDef(param))
539
540
  continue;
540
541
 
541
- CallPESet callPEs;
542
- if (param->hasIncomingEdges(SVFStmt::Call))
543
- {
544
- for (SVFStmt::SVFStmtSetTy::const_iterator cit = param->getIncomingEdgesBegin(SVFStmt::Call), ecit =
545
- param->getIncomingEdgesEnd(SVFStmt::Call); cit != ecit; ++cit)
546
- {
547
- CallPE* callPE = SVFUtil::cast<CallPE>(*cit);
548
- if (isInterestedSVFVar(callPE->getRHSVar()))
549
- callPEs.insert(callPE);
550
- }
551
- }
552
- addFormalParmVFGNode(param,func,callPEs);
542
+ const CallPE* callPE = pag->getCallPEForFormalParm(param);
543
+ addFormalParmVFGNode(param,func,callPE);
553
544
  }
554
545
 
555
546
  if (func->isVarArg())
@@ -558,18 +549,8 @@ void VFG::addVFGNodes()
558
549
  if (isInterestedSVFVar(varParam) == false || hasBlackHoleConstObjAddrAsDef(varParam))
559
550
  continue;
560
551
 
561
- CallPESet callPEs;
562
- if (varParam->hasIncomingEdges(SVFStmt::Call))
563
- {
564
- for(SVFStmt::SVFStmtSetTy::const_iterator cit = varParam->getIncomingEdgesBegin(SVFStmt::Call),
565
- ecit = varParam->getIncomingEdgesEnd(SVFStmt::Call); cit!=ecit; ++cit)
566
- {
567
- CallPE* callPE = SVFUtil::cast<CallPE>(*cit);
568
- if(isInterestedSVFVar(callPE->getRHSVar()))
569
- callPEs.insert(callPE);
570
- }
571
- }
572
- addFormalParmVFGNode(varParam,func,callPEs);
552
+ const CallPE* varCallPE = pag->getCallPEForFormalParm(varParam);
553
+ addFormalParmVFGNode(varParam,func,varCallPE);
573
554
  }
574
555
  }
575
556
 
@@ -802,12 +783,17 @@ void VFG::connectDirectVFGEdges()
802
783
  }
803
784
  else if(FormalParmVFGNode* formalParm = SVFUtil::dyn_cast<FormalParmVFGNode>(node))
804
785
  {
805
- for(CallPESet::const_iterator it = formalParm->callPEBegin(), eit = formalParm->callPEEnd();
806
- it!=eit; ++it)
786
+ if(const CallPE* callPE = formalParm->getCallPE())
807
787
  {
808
- const CallICFGNode* cs = (*it)->getCallSite();
809
- ActualParmVFGNode* acutalParm = getActualParmVFGNode((*it)->getRHSVar(),cs);
810
- addInterEdgeFromAPToFP(acutalParm,formalParm,getCallSiteID(cs, formalParm->getFun()));
788
+ for(u32_t i = 0; i < callPE->getOpVarNum(); i++)
789
+ {
790
+ if(isInterestedSVFVar(callPE->getOpVar(i)))
791
+ {
792
+ const CallICFGNode* cs = callPE->getOpCallICFGNode(i);
793
+ ActualParmVFGNode* acutalParm = getActualParmVFGNode(callPE->getOpVar(i), cs);
794
+ addInterEdgeFromAPToFP(acutalParm,formalParm,getCallSiteID(cs, formalParm->getFun()));
795
+ }
796
+ }
811
797
  }
812
798
  }
813
799
  else if(FormalRetVFGNode* calleeRet = SVFUtil::dyn_cast<FormalRetVFGNode>(node))
@@ -836,9 +822,16 @@ void VFG::connectDirectVFGEdges()
836
822
  forks.end(); iter != eiter; ++iter)
837
823
  {
838
824
  TDForkPE* forkedge = SVFUtil::cast<TDForkPE>(*iter);
839
- ActualParmVFGNode* acutalParm = getActualParmVFGNode(forkedge->getRHSVar(),forkedge->getCallSite());
840
- FormalParmVFGNode* formalParm = getFormalParmVFGNode(forkedge->getLHSVar());
841
- addInterEdgeFromAPToFP(acutalParm,formalParm,getCallSiteID(forkedge->getCallSite(), formalParm->getFun()));
825
+ FormalParmVFGNode* formalParm = getFormalParmVFGNode(forkedge->getRes());
826
+ for(u32_t i = 0; i < forkedge->getOpVarNum(); i++)
827
+ {
828
+ if(isInterestedSVFVar(forkedge->getOpVar(i)))
829
+ {
830
+ const CallICFGNode* cs = forkedge->getOpCallICFGNode(i);
831
+ ActualParmVFGNode* acutalParm = getActualParmVFGNode(forkedge->getOpVar(i), cs);
832
+ addInterEdgeFromAPToFP(acutalParm,formalParm,getCallSiteID(cs, formalParm->getFun()));
833
+ }
834
+ }
842
835
  }
843
836
  /// add join edge
844
837
  SVFStmt::SVFStmtSetTy& joins = getSVFStmtSet(SVFStmt::ThreadJoin);
@@ -231,7 +231,7 @@ void PAGBuilderFromFile::addEdge(NodeID srcID, NodeID dstID,
231
231
  else if (edge == "variant-gep")
232
232
  pag->addVariantGepStmt(srcID, dstID, AccessPath(offsetOrCSId));
233
233
  else if (edge == "call")
234
- pag->addEdge(srcNode, dstNode, new CallPE(srcNode, dstNode, nullptr, nullptr));
234
+ pag->addEdge(srcNode, dstNode, new CallPE(SVFUtil::cast<ValVar>(dstNode), {SVFUtil::cast<ValVar>(srcNode)}, {nullptr}, nullptr));
235
235
  else if (edge == "ret")
236
236
  pag->addEdge(srcNode, dstNode, new RetPE(srcNode, dstNode, nullptr,nullptr));
237
237
  else if (edge == "cmp")
@@ -305,26 +305,33 @@ void SVFIR::addStoreStmt(StoreStmt* edge, SVFVar* src, SVFVar* dst)
305
305
  }
306
306
 
307
307
  /*!
308
- * Add Call edge
308
+ * Add Call edge (phi-like: merges actual params from all call sites into formal param)
309
309
  */
310
310
  CallPE* SVFIR::addCallPE(NodeID src, NodeID dst, const CallICFGNode* cs, const FunEntryICFGNode* entry)
311
311
  {
312
- SVFVar* srcNode = getGNode(src);
313
- SVFVar* dstNode = getGNode(dst);
314
- if(hasLabeledEdge(srcNode,dstNode, SVFStmt::Call, cs))
315
- return nullptr;
316
- else
312
+ ValVar* opNode = const_cast<ValVar*>(getValVar(src));
313
+ ValVar* resNode = const_cast<ValVar*>(getValVar(dst));
314
+ FParmToCallPEMap::iterator it = fParmToCallPEMap.find(resNode);
315
+ // if first operand, create a new CallPE, otherwise add the operand to the existing CallPE
316
+ if(it == fParmToCallPEMap.end())
317
317
  {
318
- CallPE* callPE = new CallPE(srcNode, dstNode, cs,entry);
319
- addCallPE(callPE,srcNode,dstNode);
318
+ CallPE* callPE = new CallPE(resNode, {opNode}, {cs}, entry);
319
+ addCallPE(callPE, opNode, resNode);
320
320
  return callPE;
321
321
  }
322
+ else
323
+ {
324
+ it->second->addOpVar(opNode, cs);
325
+ /// return null if we already added this CallPE
326
+ return nullptr;
327
+ }
322
328
  }
323
329
 
324
330
  void SVFIR::addCallPE(CallPE* edge, SVFVar* src, SVFVar* dst)
325
331
  {
326
332
  addToStmt2TypeMap(edge);
327
- addEdge(src,dst, edge);
333
+ addEdge(src, dst, edge);
334
+ fParmToCallPEMap[dst] = edge;
328
335
  }
329
336
 
330
337
  /*!
@@ -366,16 +373,23 @@ SVFStmt* SVFIR::addBlackHoleAddrStmt(NodeID node)
366
373
  */
367
374
  TDForkPE* SVFIR::addThreadForkPE(NodeID src, NodeID dst, const CallICFGNode* cs, const FunEntryICFGNode* entry)
368
375
  {
369
- SVFVar* srcNode = getGNode(src);
370
- SVFVar* dstNode = getGNode(dst);
371
- if(hasLabeledEdge(srcNode,dstNode, SVFStmt::ThreadFork, cs))
372
- return nullptr;
373
- else
376
+ ValVar* opNode = const_cast<ValVar*>(getValVar(src));
377
+ ValVar* resNode = const_cast<ValVar*>(getValVar(dst));
378
+ FParmToCallPEMap::iterator it = fParmToCallPEMap.find(resNode);
379
+ // if first operand, create a new TDForkPE, otherwise add the operand to the existing TDForkPE
380
+ if(it == fParmToCallPEMap.end())
374
381
  {
375
- TDForkPE* forkPE = new TDForkPE(srcNode, dstNode, cs, entry);
376
- addCallPE(forkPE,srcNode,dstNode);
382
+ TDForkPE* forkPE = new TDForkPE(resNode, {opNode}, {cs}, entry);
383
+ addToStmt2TypeMap(forkPE);
384
+ addEdge(opNode, resNode, forkPE);
385
+ fParmToCallPEMap[resNode] = forkPE;
377
386
  return forkPE;
378
387
  }
388
+ else
389
+ {
390
+ it->second->addOpVar(opNode, cs);
391
+ return nullptr;
392
+ }
379
393
  }
380
394
 
381
395
  /*!
@@ -242,7 +242,14 @@ const std::string CallPE::toString() const
242
242
  {
243
243
  std::string str;
244
244
  std::stringstream rawstr(str);
245
- rawstr << "CallPE: [Var" << getLHSVarID() << " <-- Var" << getRHSVarID() << "]\t";
245
+ rawstr << "CallPE: [Var" << getResID() << " <-- (";
246
+ for (u32_t i = 0; i < getOpVarNum(); i++)
247
+ {
248
+ rawstr << "[Var" << getOpVarID(i) << ", ICFGNode" << getOpCallICFGNode(i)->getId() << "]";
249
+ if (i + 1 < getOpVarNum())
250
+ rawstr << ", ";
251
+ }
252
+ rawstr << ")] ";
246
253
  if (Options::ShowSVFIRValue())
247
254
  {
248
255
  rawstr << "\n";
@@ -268,7 +275,14 @@ const std::string TDForkPE::toString() const
268
275
  {
269
276
  std::string str;
270
277
  std::stringstream rawstr(str);
271
- rawstr << "TDForkPE: [Var" << getLHSVarID() << " <-- Var" << getRHSVarID() << "]\t";
278
+ rawstr << "TDForkPE: [Var" << getResID() << " <-- (";
279
+ for (u32_t i = 0; i < getOpVarNum(); i++)
280
+ {
281
+ rawstr << "[Var" << getOpVarID(i) << ", ICFGNode" << getOpCallICFGNode(i)->getId() << "]";
282
+ if (i + 1 < getOpVarNum())
283
+ rawstr << ", ";
284
+ }
285
+ rawstr << ")] ";
272
286
  if (Options::ShowSVFIRValue())
273
287
  {
274
288
  rawstr << "\n";
@@ -375,22 +389,6 @@ const ValVar* GepStmt::getDstNode() const
375
389
  return getLHSVar();
376
390
  }
377
391
 
378
- const ValVar* CallPE::getRHSVar() const
379
- {
380
- return cast<ValVar>(SVFStmt::getSrcNode());
381
- }
382
- const ValVar* CallPE::getLHSVar() const
383
- {
384
- return cast<ValVar>(SVFStmt::getDstNode());
385
- }
386
- const ValVar* CallPE::getSrcNode() const
387
- {
388
- return getRHSVar();
389
- }
390
- const ValVar* CallPE::getDstNode() const
391
- {
392
- return getLHSVar();
393
- }
394
392
 
395
393
  const ValVar* RetPE::getRHSVar() const
396
394
  {
@@ -409,22 +407,6 @@ const ValVar* RetPE::getDstNode() const
409
407
  return getLHSVar();
410
408
  }
411
409
 
412
- const ValVar* TDForkPE::getRHSVar() const
413
- {
414
- return cast<ValVar>(SVFStmt::getSrcNode());
415
- }
416
- const ValVar* TDForkPE::getLHSVar() const
417
- {
418
- return cast<ValVar>(SVFStmt::getDstNode());
419
- }
420
- const ValVar* TDForkPE::getSrcNode() const
421
- {
422
- return getRHSVar();
423
- }
424
- const ValVar* TDForkPE::getDstNode() const
425
- {
426
- return getLHSVar();
427
- }
428
410
 
429
411
  const ValVar* TDJoinPE::getRHSVar() const
430
412
  {
@@ -518,10 +500,16 @@ StoreStmt::StoreStmt(SVFVar* s, SVFVar* d, const ICFGNode* st)
518
500
  {
519
501
  }
520
502
 
521
- CallPE::CallPE(SVFVar* s, SVFVar* d, const CallICFGNode* i,
522
- const FunEntryICFGNode* e, GEdgeKind k)
523
- : AssignStmt(s, d, makeEdgeFlagWithCallInst(k, i)), call(i), entry(e)
503
+ CallPE::CallPE(ValVar* res, const OPVars& opnds,
504
+ const CallICFGNodeVec& icfgNodes,
505
+ const FunEntryICFGNode* e,
506
+ GEdgeKind k)
507
+ : MultiOpndStmt(res, opnds,
508
+ makeEdgeFlagWithAddionalOpnd(k, opnds.at(0))),
509
+ opCallICFGNodes(icfgNodes), entry(e)
524
510
  {
511
+ assert(opnds.size() == icfgNodes.size() &&
512
+ "Numbers of operands and their CallICFGNodes are not consistent?");
525
513
  }
526
514
 
527
515
 
@@ -1767,12 +1767,18 @@ void SVFIRBuilder::setCurrentBBAndValueForPAGEdge(PAGEdge* edge)
1767
1767
  {
1768
1768
  icfgNode = pag->getICFG()->getFunExitICFGNode(llvmMS->getFunObjVar(curInst->getFunction()));
1769
1769
  }
1770
+ else if(const CallPE* callPE = SVFUtil::dyn_cast<CallPE>(edge))
1771
+ {
1772
+ /// CallPE is placed at FunEntryICFGNode (phi-like merging of actual params)
1773
+ icfgNode = const_cast<FunEntryICFGNode*>(callPE->getFunEntryICFGNode());
1774
+ }
1775
+ else if(SVFUtil::isa<RetPE>(edge))
1776
+ {
1777
+ icfgNode = llvmMS->getRetICFGNode(SVFUtil::cast<Instruction>(curInst));
1778
+ }
1770
1779
  else
1771
1780
  {
1772
- if(SVFUtil::isa<RetPE>(edge))
1773
- icfgNode = llvmMS->getRetICFGNode(SVFUtil::cast<Instruction>(curInst));
1774
- else
1775
- icfgNode = llvmMS->getICFGNode(SVFUtil::cast<Instruction>(curInst));
1781
+ icfgNode = llvmMS->getICFGNode(SVFUtil::cast<Instruction>(curInst));
1776
1782
  }
1777
1783
  }
1778
1784
  else if (const Argument* arg = SVFUtil::dyn_cast<Argument>(curVal))
@@ -1801,10 +1807,15 @@ void SVFIRBuilder::setCurrentBBAndValueForPAGEdge(PAGEdge* edge)
1801
1807
  icfgNode->addSVFStmt(edge);
1802
1808
  if(const CallPE* callPE = SVFUtil::dyn_cast<CallPE>(edge))
1803
1809
  {
1804
- CallICFGNode* callNode = const_cast<CallICFGNode*>(callPE->getCallSite());
1810
+ /// CallPE is phi-like at FunEntryICFGNode. Collect it on each CallCFGEdge
1811
+ /// whose call site appears as an operand, so the edge knows which params are passed.
1805
1812
  FunEntryICFGNode* entryNode = const_cast<FunEntryICFGNode*>(callPE->getFunEntryICFGNode());
1806
- if(ICFGEdge* edge = pag->getICFG()->hasInterICFGEdge(callNode,entryNode, ICFGEdge::CallCF))
1807
- SVFUtil::cast<CallCFGEdge>(edge)->addCallPE(callPE);
1813
+ for(u32_t i = 0; i < callPE->getOpVarNum(); i++)
1814
+ {
1815
+ CallICFGNode* callNode = const_cast<CallICFGNode*>(callPE->getOpCallICFGNode(i));
1816
+ if(ICFGEdge* icfgEdge = pag->getICFG()->hasInterICFGEdge(callNode, entryNode, ICFGEdge::CallCF))
1817
+ SVFUtil::cast<CallCFGEdge>(icfgEdge)->addCallPE(callPE);
1818
+ }
1808
1819
  }
1809
1820
  else if(const RetPE* retPE = SVFUtil::dyn_cast<RetPE>(edge))
1810
1821
  {