svf-tools 1.0.1005 → 1.0.1007

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.1005",
3
+ "version": "1.0.1007",
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": {
@@ -0,0 +1,264 @@
1
+ //===- CallGraph.h -- Call graph representation----------------------------//
2
+ //
3
+ // SVF: Static Value-Flow Analysis
4
+ //
5
+ // Copyright (C) <2013-2017> <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
+ * CallGraph.h
25
+ *
26
+ * Created on: Nov 7, 2013
27
+ * Author: Yulei Sui
28
+ */
29
+
30
+ #ifndef CALLGRAPH_H_
31
+ #define CALLGRAPH_H_
32
+
33
+ #include "Graphs/GenericGraph.h"
34
+ #include "SVFIR/SVFValue.h"
35
+ #include "Graphs/ICFG.h"
36
+ #include <set>
37
+
38
+ namespace SVF
39
+ {
40
+
41
+ class CallGraphNode;
42
+ class SVFModule;
43
+
44
+
45
+ /*
46
+ * Call Graph edge representing a calling relation between two functions
47
+ * Multiple calls from function A to B are merged into one call edge
48
+ * Each call edge has a set of direct callsites and a set of indirect callsites
49
+ */
50
+ typedef GenericEdge<CallGraphNode> GenericCallGraphEdgeTy;
51
+ class CallGraphEdge : public GenericCallGraphEdgeTy
52
+ {
53
+
54
+ public:
55
+ typedef Set<const CallICFGNode*> CallInstSet;
56
+
57
+ private:
58
+ CallInstSet directCalls;
59
+ public:
60
+ /// Constructor
61
+ CallGraphEdge(CallGraphNode* s, CallGraphNode* d, const CallICFGNode* icfgNode) :
62
+ GenericCallGraphEdgeTy(s, d, icfgNode->getId())
63
+ {
64
+ }
65
+ /// Destructor
66
+ virtual ~CallGraphEdge()
67
+ {
68
+ }
69
+
70
+ /// Add direct callsite
71
+ //@{
72
+ void addDirectCallSite(const CallICFGNode* call);
73
+ //@}
74
+
75
+ /// Iterators for direct and indirect callsites
76
+ //@{
77
+ inline CallInstSet::const_iterator directCallsBegin() const
78
+ {
79
+ return directCalls.begin();
80
+ }
81
+ inline CallInstSet::const_iterator directCallsEnd() const
82
+ {
83
+ return directCalls.end();
84
+ }
85
+ //@}
86
+
87
+ /// ClassOf
88
+ //@{
89
+ static inline bool classof(const CallGraphEdge*)
90
+ {
91
+ return true;
92
+ }
93
+ //@}
94
+
95
+ /// Overloading operator << for dumping ICFG node ID
96
+ //@{
97
+ friend OutStream& operator<< (OutStream &o, const CallGraphEdge&edge)
98
+ {
99
+ o << edge.toString();
100
+ return o;
101
+ }
102
+ //@}
103
+
104
+ virtual const std::string toString() const;
105
+
106
+ typedef GenericNode<CallGraphNode, CallGraphEdge>::GEdgeSetTy CallGraphEdgeSet;
107
+
108
+ };
109
+
110
+ /*
111
+ * Call Graph node representing a function
112
+ */
113
+ typedef GenericNode<CallGraphNode, CallGraphEdge> GenericCallGraphNodeTy;
114
+ class CallGraphNode : public GenericCallGraphNodeTy
115
+ {
116
+ private:
117
+ const SVFFunction* fun;
118
+
119
+ public:
120
+ /// Constructor
121
+ CallGraphNode(NodeID i, const SVFFunction* f) : GenericCallGraphNodeTy(i,CallNodeKd), fun(f)
122
+ {
123
+ }
124
+
125
+ inline const std::string &getName() const
126
+ {
127
+ return fun->getName();
128
+ }
129
+
130
+ /// Get function of this call node
131
+ inline const SVFFunction* getFunction() const
132
+ {
133
+ return fun;
134
+ }
135
+
136
+
137
+ /// Overloading operator << for dumping ICFG node ID
138
+ //@{
139
+ friend OutStream& operator<< (OutStream &o, const CallGraphNode&node)
140
+ {
141
+ o << node.toString();
142
+ return o;
143
+ }
144
+ //@}
145
+
146
+ virtual const std::string toString() const;
147
+
148
+ /// Methods for support type inquiry through isa, cast, and dyn_cast:
149
+ //@{
150
+ static inline bool classof(const CallGraphNode*)
151
+ {
152
+ return true;
153
+ }
154
+
155
+ static inline bool classof(const GenericICFGNodeTy* node)
156
+ {
157
+ return node->getNodeKind() == CallNodeKd;
158
+ }
159
+
160
+ static inline bool classof(const SVFBaseNode* node)
161
+ {
162
+ return node->getNodeKind() == CallNodeKd;
163
+ }
164
+ //@}
165
+ };
166
+
167
+ /*!
168
+ * Pointer Analysis Call Graph used internally for various pointer analysis
169
+ */
170
+ typedef GenericGraph<CallGraphNode, CallGraphEdge> GenericCallGraphTy;
171
+ class CallGraph : public GenericCallGraphTy
172
+ {
173
+ friend class PTACallGraph;
174
+
175
+ public:
176
+ typedef CallGraphEdge::CallGraphEdgeSet CallGraphEdgeSet;
177
+ typedef Map<const SVFFunction*, CallGraphNode*> FunToCallGraphNodeMap;
178
+ typedef Map<const CallICFGNode*, CallGraphEdgeSet> CallInstToCallGraphEdgesMap;
179
+ typedef Set<const SVFFunction*> FunctionSet;
180
+ typedef OrderedMap<const CallICFGNode*, FunctionSet> CallEdgeMap;
181
+
182
+ protected:
183
+ FunToCallGraphNodeMap funToCallGraphNodeMap; ///< Call Graph node map
184
+ CallInstToCallGraphEdgesMap callinstToCallGraphEdgesMap; ///< Map a call instruction to its corresponding call edges
185
+
186
+ NodeID callGraphNodeNum;
187
+
188
+ /// Clean up memory
189
+ void destroy();
190
+
191
+ /// Add call graph edge
192
+ inline void addEdge(CallGraphEdge* edge)
193
+ {
194
+ edge->getDstNode()->addIncomingEdge(edge);
195
+ edge->getSrcNode()->addOutgoingEdge(edge);
196
+ }
197
+
198
+
199
+ public:
200
+ /// Constructor
201
+ CallGraph();
202
+
203
+ void addCallGraphNode(const SVFFunction* fun);
204
+
205
+ /// Destructor
206
+ virtual ~CallGraph()
207
+ {
208
+ destroy();
209
+ }
210
+
211
+ /// Get call graph node
212
+ //@{
213
+ inline CallGraphNode* getCallGraphNode(NodeID id) const
214
+ {
215
+ return getGNode(id);
216
+ }
217
+ inline CallGraphNode* getCallGraphNode(const SVFFunction* fun) const
218
+ {
219
+ FunToCallGraphNodeMap::const_iterator it = funToCallGraphNodeMap.find(fun);
220
+ assert(it!=funToCallGraphNodeMap.end() && "call graph node not found!!");
221
+ return it->second;
222
+ }
223
+
224
+ //@}
225
+
226
+ /// Whether we have already created this call graph edge
227
+ CallGraphEdge* hasGraphEdge(CallGraphNode* src, CallGraphNode* dst,
228
+ const CallICFGNode* callIcfgNode) const;
229
+
230
+ /// Add direct call edges
231
+ void addDirectCallGraphEdge(const CallICFGNode* call, const SVFFunction* callerFun, const SVFFunction* calleeFun);
232
+ /// Dump the graph
233
+ void dump(const std::string& filename);
234
+
235
+ /// View the graph from the debugger
236
+ void view();
237
+ };
238
+
239
+ } // End namespace SVF
240
+
241
+ namespace SVF
242
+ {
243
+ /* !
244
+ * GenericGraphTraits specializations for generic graph algorithms.
245
+ * Provide graph traits for traversing from a constraint node using standard graph traversals.
246
+ */
247
+ template<> struct GenericGraphTraits<SVF::CallGraphNode*> : public GenericGraphTraits<SVF::GenericNode<SVF::CallGraphNode,SVF::CallGraphEdge>* >
248
+ {
249
+ };
250
+
251
+ /// Inverse GenericGraphTraits specializations for call graph node, it is used for inverse traversal.
252
+ template<>
253
+ struct GenericGraphTraits<Inverse<SVF::CallGraphNode*> > : public GenericGraphTraits<Inverse<SVF::GenericNode<SVF::CallGraphNode,SVF::CallGraphEdge>* > >
254
+ {
255
+ };
256
+
257
+ template<> struct GenericGraphTraits<SVF::CallGraph*> : public GenericGraphTraits<SVF::GenericGraph<SVF::CallGraphNode,SVF::CallGraphEdge>* >
258
+ {
259
+ typedef SVF::CallGraphNode*NodeRef;
260
+ };
261
+
262
+ } // End namespace llvm
263
+
264
+ #endif /* CALLGRAPH_H_ */
@@ -40,6 +40,7 @@ namespace SVF
40
40
 
41
41
  class PTACallGraphNode;
42
42
  class SVFModule;
43
+ class CallGraph;
43
44
 
44
45
 
45
46
  /*
@@ -47,8 +48,8 @@ class SVFModule;
47
48
  * Multiple calls from function A to B are merged into one call edge
48
49
  * Each call edge has a set of direct callsites and a set of indirect callsites
49
50
  */
50
- typedef GenericEdge<PTACallGraphNode> GenericCallGraphEdgeTy;
51
- class PTACallGraphEdge : public GenericCallGraphEdgeTy
51
+ typedef GenericEdge<PTACallGraphNode> GenericPTACallGraphEdgeTy;
52
+ class PTACallGraphEdge : public GenericPTACallGraphEdgeTy
52
53
  {
53
54
 
54
55
  public:
@@ -66,7 +67,7 @@ private:
66
67
  public:
67
68
  /// Constructor
68
69
  PTACallGraphEdge(PTACallGraphNode* s, PTACallGraphNode* d, CEDGEK kind, CallSiteID cs) :
69
- GenericCallGraphEdgeTy(s, d, makeEdgeFlagWithInvokeID(kind, cs)), csId(cs)
70
+ GenericPTACallGraphEdgeTy(s, d, makeEdgeFlagWithInvokeID(kind, cs)), csId(cs)
70
71
  {
71
72
  }
72
73
  /// Destructor
@@ -144,7 +145,7 @@ public:
144
145
  {
145
146
  return true;
146
147
  }
147
- static inline bool classof(const GenericCallGraphEdgeTy *edge)
148
+ static inline bool classof(const GenericPTACallGraphEdgeTy *edge)
148
149
  {
149
150
  return edge->getEdgeKind() == PTACallGraphEdge::CallRetEdge ||
150
151
  edge->getEdgeKind() == PTACallGraphEdge::TDForkEdge ||
@@ -170,21 +171,15 @@ public:
170
171
  /*
171
172
  * Call Graph node representing a function
172
173
  */
173
- typedef GenericNode<PTACallGraphNode, PTACallGraphEdge> GenericCallGraphNodeTy;
174
- class PTACallGraphNode : public GenericCallGraphNodeTy
174
+ typedef GenericNode<PTACallGraphNode, PTACallGraphEdge> GenericPTACallGraphNodeTy;
175
+ class PTACallGraphNode : public GenericPTACallGraphNodeTy
175
176
  {
176
-
177
- public:
178
- typedef PTACallGraphEdge::CallGraphEdgeSet CallGraphEdgeSet;
179
- typedef PTACallGraphEdge::CallGraphEdgeSet::iterator iterator;
180
- typedef PTACallGraphEdge::CallGraphEdgeSet::const_iterator const_iterator;
181
-
182
177
  private:
183
178
  const SVFFunction* fun;
184
179
 
185
180
  public:
186
181
  /// Constructor
187
- PTACallGraphNode(NodeID i, const SVFFunction* f) : GenericCallGraphNodeTy(i,CallNodeKd), fun(f)
182
+ PTACallGraphNode(NodeID i, const SVFFunction* f) : GenericPTACallGraphNodeTy(i,CallNodeKd), fun(f)
188
183
  {
189
184
 
190
185
  }
@@ -237,8 +232,8 @@ public:
237
232
  /*!
238
233
  * Pointer Analysis Call Graph used internally for various pointer analysis
239
234
  */
240
- typedef GenericGraph<PTACallGraphNode, PTACallGraphEdge> GenericCallGraphTy;
241
- class PTACallGraph : public GenericCallGraphTy
235
+ typedef GenericGraph<PTACallGraphNode, PTACallGraphEdge> GenericPTACallGraphTy;
236
+ class PTACallGraph : public GenericPTACallGraphTy
242
237
  {
243
238
 
244
239
  public:
@@ -278,14 +273,36 @@ protected:
278
273
  /// Clean up memory
279
274
  void destroy();
280
275
 
276
+ protected:
277
+ /// Add CallSiteID
278
+ inline CallSiteID addCallSite(const CallICFGNode* cs, const SVFFunction* callee)
279
+ {
280
+ std::pair<const CallICFGNode*, const SVFFunction*> newCS(std::make_pair(cs, callee));
281
+ CallSiteToIdMap::const_iterator it = csToIdMap.find(newCS);
282
+ //assert(it == csToIdMap.end() && "cannot add a callsite twice");
283
+ if(it == csToIdMap.end())
284
+ {
285
+ CallSiteID id = totalCallSiteNum++;
286
+ csToIdMap.insert(std::make_pair(newCS, id));
287
+ idToCSMap.insert(std::make_pair(id, newCS));
288
+ return id;
289
+ }
290
+ return it->second;
291
+ }
292
+
293
+ /// Add call graph edge
294
+ inline void addEdge(PTACallGraphEdge* edge)
295
+ {
296
+ edge->getDstNode()->addIncomingEdge(edge);
297
+ edge->getSrcNode()->addOutgoingEdge(edge);
298
+ }
299
+
281
300
  public:
282
301
  /// Constructor
283
302
  PTACallGraph(CGEK k = NormCallGraph);
284
303
 
285
304
  /// Copy constructor
286
- PTACallGraph(const PTACallGraph& other);
287
-
288
- void addCallGraphNode(const SVFFunction* fun);
305
+ PTACallGraph(const CallGraph& other);
289
306
 
290
307
  /// Destructor
291
308
  virtual ~PTACallGraph()
@@ -349,22 +366,8 @@ public:
349
366
 
350
367
  //@}
351
368
 
352
- /// Add/Get CallSiteID
369
+ /// Get CallSiteID
353
370
  //@{
354
- inline CallSiteID addCallSite(const CallICFGNode* cs, const SVFFunction* callee)
355
- {
356
- std::pair<const CallICFGNode*, const SVFFunction*> newCS(std::make_pair(cs, callee));
357
- CallSiteToIdMap::const_iterator it = csToIdMap.find(newCS);
358
- //assert(it == csToIdMap.end() && "cannot add a callsite twice");
359
- if(it == csToIdMap.end())
360
- {
361
- CallSiteID id = totalCallSiteNum++;
362
- csToIdMap.insert(std::make_pair(newCS, id));
363
- idToCSMap.insert(std::make_pair(id, newCS));
364
- return id;
365
- }
366
- return it->second;
367
- }
368
371
  inline CallSiteID getCallSiteID(const CallICFGNode* cs, const SVFFunction* callee) const
369
372
  {
370
373
  CallSitePair newCS(std::make_pair(cs, callee));
@@ -439,16 +442,10 @@ public:
439
442
  return it->second.end();
440
443
  }
441
444
  //@}
442
- /// Add call graph edge
443
- inline void addEdge(PTACallGraphEdge* edge)
444
- {
445
- edge->getDstNode()->addIncomingEdge(edge);
446
- edge->getSrcNode()->addOutgoingEdge(edge);
447
- }
448
445
 
449
- /// Add direct/indirect call edges
446
+
447
+ /// Add indirect call edges
450
448
  //@{
451
- void addDirectCallGraphEdge(const CallICFGNode* call, const SVFFunction* callerFun, const SVFFunction* calleeFun);
452
449
  void addIndirectCallGraphEdge(const CallICFGNode* cs,const SVFFunction* callerFun, const SVFFunction* calleeFun);
453
450
  //@}
454
451
 
@@ -494,4 +491,4 @@ template<> struct GenericGraphTraits<SVF::PTACallGraph*> : public GenericGraphTr
494
491
 
495
492
  } // End namespace llvm
496
493
 
497
- #endif /* CALLGRAPH_H_ */
494
+ #endif /* PTACALLGRAPH_H_ */
@@ -172,7 +172,7 @@ public:
172
172
  typedef Map<const CallICFGNode*, ParForEdgeSet> CallInstToParForEdgesMap;
173
173
 
174
174
  /// Constructor
175
- ThreadCallGraph(const PTACallGraph& cg);
175
+ ThreadCallGraph(const CallGraph& cg);
176
176
 
177
177
  ThreadCallGraph(ThreadCallGraph& cg) = delete;
178
178
 
@@ -515,7 +515,7 @@ public:
515
515
 
516
516
  /*!
517
517
  *
518
- * StoreCHI is annotated at each store instruction, representing a memory object is modified here
518
+ * CallCHI is annotated at callsite, representing a memory object is indirect modified by callee
519
519
  */
520
520
  template<class Cond>
521
521
  class CallCHI : public MSSACHI<Cond>
@@ -523,7 +523,7 @@ class CallCHI : public MSSACHI<Cond>
523
523
  private:
524
524
  const CallICFGNode* callsite;
525
525
  public:
526
- /// Constructors for StoreCHI
526
+ /// Constructors for CallCHI
527
527
  //@{
528
528
  CallCHI(const CallICFGNode* cs, const MemRegion* m, Cond c = true) :
529
529
  MSSACHI<Cond>(MSSADEF::CallMSSACHI,m,c), callsite(cs)
@@ -35,6 +35,7 @@
35
35
  namespace SVF
36
36
  {
37
37
  class CommonCHGraph;
38
+ class CallGraph;
38
39
  /*!
39
40
  * SVF Intermediate representation, representing variables and statements as a Program Assignment Graph (PAG)
40
41
  * Variables as nodes and statements as edges.
@@ -98,7 +99,7 @@ private:
98
99
  ICFG* icfg; // ICFG
99
100
  CommonCHGraph* chgraph; // class hierarchy graph
100
101
  CallSiteSet callSiteSet; /// all the callsites of a program
101
- PTACallGraph* callGraph; /// call graph
102
+ CallGraph* callGraph; /// call graph
102
103
 
103
104
  static std::unique_ptr<SVFIR> pag; ///< Singleton pattern here to enable instance of SVFIR can only be created once.
104
105
 
@@ -185,13 +186,13 @@ public:
185
186
  }
186
187
 
187
188
  /// Set/Get CG
188
- inline void setCallGraph(PTACallGraph* c)
189
+ inline void setCallGraph(CallGraph* c)
189
190
  {
190
191
  callGraph = c;
191
192
  }
192
- inline PTACallGraph* getCallGraph()
193
+ inline CallGraph* getCallGraph()
193
194
  {
194
- assert(callGraph && "empty PTACallGraph! Build SVF IR first!");
195
+ assert(callGraph && "empty CallGraph! Build SVF IR first!");
195
196
  return callGraph;
196
197
  }
197
198
 
@@ -31,7 +31,6 @@
31
31
  #ifndef INCLUDE_SVF_FE_CALLGRAPHBUILDER_H_
32
32
  #define INCLUDE_SVF_FE_CALLGRAPHBUILDER_H_
33
33
 
34
- #include "Graphs/PTACallGraph.h"
35
34
  #include "Graphs/ThreadCallGraph.h"
36
35
 
37
36
  namespace SVF
@@ -39,6 +38,8 @@ namespace SVF
39
38
 
40
39
  class ICFG;
41
40
  class SVFModule;
41
+ class CallGraph;
42
+ class ThreadCallGraph;
42
43
 
43
44
  class CallGraphBuilder
44
45
  {
@@ -46,7 +47,10 @@ public:
46
47
  CallGraphBuilder()=default;
47
48
 
48
49
  /// Buidl SVFIR callgraoh
49
- PTACallGraph* buildSVFIRCallGraph(SVFModule* svfModule);
50
+ CallGraph* buildSVFIRCallGraph(SVFModule* svfModule);
51
+
52
+ /// Buidl PTA callgraoh
53
+ PTACallGraph* buildPTACallGraph();
50
54
 
51
55
  /// Build thread-aware callgraph
52
56
  ThreadCallGraph* buildThreadCallGraph();
@@ -0,0 +1,211 @@
1
+ //===- CallGraph.cpp -- Call graph used internally in SVF------------------//
2
+ //
3
+ // SVF: Static Value-Flow Analysis
4
+ //
5
+ // Copyright (C) <2013-2017> <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
+ /*
25
+ * CallGraph.cpp
26
+ *
27
+ * Created on: Nov 7, 2013
28
+ * Author: Yulei Sui
29
+ */
30
+
31
+ #include "Graphs/CallGraph.h"
32
+ #include "SVFIR/SVFIR.h"
33
+ #include "SVFIR/SVFModule.h"
34
+ #include "Util/SVFUtil.h"
35
+ #include <sstream>
36
+
37
+ using namespace SVF;
38
+ using namespace SVFUtil;
39
+
40
+
41
+ /// Add direct callsite
42
+ //@{
43
+ void CallGraphEdge::addDirectCallSite(const CallICFGNode* call)
44
+ {
45
+ assert(call->getCalledFunction() && "not a direct callsite??");
46
+ directCalls.insert(call);
47
+ }
48
+ //@}
49
+
50
+ const std::string CallGraphEdge::toString() const
51
+ {
52
+ std::string str;
53
+ std::stringstream rawstr(str);
54
+ rawstr << "CallICFGNode ID: " << getEdgeKindWithoutMask();
55
+ rawstr << "direct call";
56
+ rawstr << "[" << getDstID() << "<--" << getSrcID() << "]\t";
57
+ return rawstr.str();
58
+ }
59
+
60
+ const std::string CallGraphNode::toString() const
61
+ {
62
+ std::string str;
63
+ std::stringstream rawstr(str);
64
+ rawstr << "CallGraphNode ID: " << getId() << " {fun: " << fun->getName() << "}";
65
+ return rawstr.str();
66
+ }
67
+
68
+
69
+ /// Constructor
70
+ CallGraph::CallGraph()
71
+ {
72
+ callGraphNodeNum = 0;
73
+ }
74
+
75
+
76
+ /*!
77
+ * Memory has been cleaned up at GenericGraph
78
+ */
79
+ void CallGraph::destroy()
80
+ {
81
+ }
82
+
83
+ /*!
84
+ * Add call graph node
85
+ */
86
+ void CallGraph::addCallGraphNode(const SVFFunction* fun)
87
+ {
88
+ NodeID id = callGraphNodeNum;
89
+ CallGraphNode*callGraphNode = new CallGraphNode(id, fun);
90
+ addGNode(id, callGraphNode);
91
+ funToCallGraphNodeMap[callGraphNode->getFunction()] = callGraphNode;
92
+ callGraphNodeNum++;
93
+ }
94
+
95
+ /*!
96
+ * Whether we have already created this call graph edge
97
+ */
98
+ CallGraphEdge* CallGraph::hasGraphEdge(CallGraphNode* src,
99
+ CallGraphNode* dst,
100
+ const CallICFGNode* callIcfgNode) const
101
+ {
102
+ CallGraphEdge edge(src,dst,callIcfgNode);
103
+ CallGraphEdge* outEdge = src->hasOutgoingEdge(&edge);
104
+ CallGraphEdge* inEdge = dst->hasIncomingEdge(&edge);
105
+ if (outEdge && inEdge)
106
+ {
107
+ assert(outEdge == inEdge && "edges not match");
108
+ return outEdge;
109
+ }
110
+ else
111
+ return nullptr;
112
+ }
113
+
114
+ /*!
115
+ * Add direct call edges
116
+ */
117
+ void CallGraph::addDirectCallGraphEdge(const CallICFGNode* cs,const SVFFunction* callerFun, const SVFFunction* calleeFun)
118
+ {
119
+
120
+ CallGraphNode* caller = getCallGraphNode(callerFun);
121
+ CallGraphNode* callee = getCallGraphNode(calleeFun);
122
+
123
+
124
+ if(!hasGraphEdge(caller,callee, cs))
125
+ {
126
+ CallGraphEdge* edge = new CallGraphEdge(caller,callee, cs);
127
+ edge->addDirectCallSite(cs);
128
+ addEdge(edge);
129
+ callinstToCallGraphEdgesMap[cs].insert(edge);
130
+ }
131
+ }
132
+
133
+ /*!
134
+ * Dump call graph into dot file
135
+ */
136
+ void CallGraph::dump(const std::string& filename)
137
+ {
138
+ GraphPrinter::WriteGraphToFile(outs(), filename, this);
139
+ }
140
+
141
+ void CallGraph::view()
142
+ {
143
+ SVF::ViewGraph(this, "Call Graph");
144
+ }
145
+
146
+ namespace SVF
147
+ {
148
+
149
+ /*!
150
+ * Write value flow graph into dot file for debugging
151
+ */
152
+ template<>
153
+ struct DOTGraphTraits<CallGraph*> : public DefaultDOTGraphTraits
154
+ {
155
+
156
+ typedef CallGraphNode NodeType;
157
+ typedef NodeType::iterator ChildIteratorType;
158
+ DOTGraphTraits(bool isSimple = false) :
159
+ DefaultDOTGraphTraits(isSimple)
160
+ {
161
+ }
162
+
163
+ /// Return name of the graph
164
+ static std::string getGraphName(CallGraph*)
165
+ {
166
+ return "Call Graph";
167
+ }
168
+ /// Return function name;
169
+ static std::string getNodeLabel(CallGraphNode*node, CallGraph*)
170
+ {
171
+ return node->toString();
172
+ }
173
+
174
+ static std::string getNodeAttributes(CallGraphNode*node, CallGraph*)
175
+ {
176
+ const SVFFunction* fun = node->getFunction();
177
+ if (!SVFUtil::isExtCall(fun))
178
+ {
179
+ return "shape=box";
180
+ }
181
+ else
182
+ return "shape=Mrecord";
183
+ }
184
+
185
+ template<class EdgeIter>
186
+ static std::string getEdgeAttributes(CallGraphNode*, EdgeIter EI,
187
+ CallGraph*)
188
+ {
189
+
190
+ //TODO: mark indirect call of Fork with different color
191
+ CallGraphEdge* edge = *(EI.getCurrent());
192
+ assert(edge && "No edge found!!");
193
+
194
+ std::string color = "color=black";
195
+ return color;
196
+ }
197
+
198
+ template<class EdgeIter>
199
+ static std::string getEdgeSourceLabel(NodeType*, EdgeIter EI)
200
+ {
201
+ CallGraphEdge* edge = *(EI.getCurrent());
202
+ assert(edge && "No edge found!!");
203
+
204
+ std::string str;
205
+ std::stringstream rawstr(str);
206
+ rawstr << edge->getEdgeKindWithoutMask();
207
+
208
+ return rawstr.str();
209
+ }
210
+ };
211
+ } // End namespace llvm
@@ -29,6 +29,7 @@
29
29
  */
30
30
 
31
31
  #include "Graphs/PTACallGraph.h"
32
+ #include "Graphs/CallGraph.h"
32
33
  #include "SVFIR/SVFIR.h"
33
34
  #include "SVFIR/SVFModule.h"
34
35
  #include "Util/SVFUtil.h"
@@ -39,8 +40,7 @@ using namespace SVFUtil;
39
40
 
40
41
  PTACallGraph::CallSiteToIdMap PTACallGraph::csToIdMap;
41
42
  PTACallGraph::IdToCallSiteMap PTACallGraph::idToCSMap;
42
- CallSiteID PTACallGraph::totalCallSiteNum = 1;
43
-
43
+ CallSiteID PTACallGraph::totalCallSiteNum=1;
44
44
 
45
45
  /// Add direct and indirect callsite
46
46
  //@{
@@ -113,16 +113,16 @@ PTACallGraph::PTACallGraph(CGEK k): kind(k)
113
113
  }
114
114
 
115
115
  /// Copy constructor
116
- PTACallGraph::PTACallGraph(const PTACallGraph& other)
116
+ PTACallGraph::PTACallGraph(const CallGraph& other)
117
117
  {
118
- callGraphNodeNum = other.callGraphNodeNum;
118
+ callGraphNodeNum = other.getTotalNodeNum();
119
119
  numOfResolvedIndCallEdge = 0;
120
- kind = other.kind;
120
+ kind = NormCallGraph;
121
121
 
122
122
  /// copy call graph nodes
123
123
  for (const auto& item : other)
124
124
  {
125
- const PTACallGraphNode* cgn = item.second;
125
+ const CallGraphNode* cgn = item.second;
126
126
  PTACallGraphNode* callGraphNode = new PTACallGraphNode(cgn->getId(), cgn->getFunction());
127
127
  addGNode(cgn->getId(),callGraphNode);
128
128
  funToCallGraphNodeMap[cgn->getFunction()] = callGraphNode;
@@ -132,11 +132,13 @@ PTACallGraph::PTACallGraph(const PTACallGraph& other)
132
132
  for (const auto& item : other.callinstToCallGraphEdgesMap)
133
133
  {
134
134
  const CallICFGNode* cs = item.first;
135
- for (const PTACallGraphEdge* edge : item.second)
135
+ for (const CallGraphEdge* edge : item.second)
136
136
  {
137
137
  PTACallGraphNode* src = getCallGraphNode(edge->getSrcID());
138
138
  PTACallGraphNode* dst = getCallGraphNode(edge->getDstID());
139
- PTACallGraphEdge* newEdge = new PTACallGraphEdge(src,dst, PTACallGraphEdge::CallRetEdge,edge->getCallSiteID());
139
+ CallSiteID csId = addCallSite(cs, dst->getFunction());
140
+
141
+ PTACallGraphEdge* newEdge = new PTACallGraphEdge(src,dst, PTACallGraphEdge::CallRetEdge,csId);
140
142
  newEdge->addDirectCallSite(cs);
141
143
  addEdge(newEdge);
142
144
  callinstToCallGraphEdgesMap[cs].insert(newEdge);
@@ -152,18 +154,6 @@ void PTACallGraph::destroy()
152
154
  {
153
155
  }
154
156
 
155
- /*!
156
- * Add call graph node
157
- */
158
- void PTACallGraph::addCallGraphNode(const SVFFunction* fun)
159
- {
160
- NodeID id = callGraphNodeNum;
161
- PTACallGraphNode*callGraphNode = new PTACallGraphNode(id, fun);
162
- addGNode(id, callGraphNode);
163
- funToCallGraphNodeMap[callGraphNode->getFunction()] = callGraphNode;
164
- callGraphNodeNum++;
165
- }
166
-
167
157
  /*!
168
158
  * Whether we have already created this call graph edge
169
159
  */
@@ -200,25 +190,6 @@ PTACallGraphEdge* PTACallGraph::getGraphEdge(PTACallGraphNode* src,
200
190
  return nullptr;
201
191
  }
202
192
 
203
- /*!
204
- * Add direct call edges
205
- */
206
- void PTACallGraph::addDirectCallGraphEdge(const CallICFGNode* cs,const SVFFunction* callerFun, const SVFFunction* calleeFun)
207
- {
208
-
209
- PTACallGraphNode* caller = getCallGraphNode(callerFun);
210
- PTACallGraphNode* callee = getCallGraphNode(calleeFun);
211
-
212
- CallSiteID csId = addCallSite(cs, callee->getFunction());
213
-
214
- if(!hasGraphEdge(caller,callee, PTACallGraphEdge::CallRetEdge,csId))
215
- {
216
- PTACallGraphEdge* edge = new PTACallGraphEdge(caller,callee, PTACallGraphEdge::CallRetEdge,csId);
217
- edge->addDirectCallSite(cs);
218
- addEdge(edge);
219
- callinstToCallGraphEdgesMap[cs].insert(edge);
220
- }
221
- }
222
193
 
223
194
  /*!
224
195
  * Add indirect call edge to update call graph
@@ -39,7 +39,7 @@ using namespace SVFUtil;
39
39
  /*!
40
40
  * Constructor
41
41
  */
42
- ThreadCallGraph::ThreadCallGraph(const PTACallGraph& cg) :
42
+ ThreadCallGraph::ThreadCallGraph(const CallGraph& cg) :
43
43
  PTACallGraph(cg), tdAPI(ThreadAPI::getThreadAPI())
44
44
  {
45
45
  kind = ThdCallGraph;
@@ -31,6 +31,7 @@
31
31
  #include "SVFIR/SVFModule.h"
32
32
  #include "MSSA/MemRegion.h"
33
33
  #include "MSSA/MSSAMuChi.h"
34
+ #include "Graphs/CallGraph.h"
34
35
 
35
36
  using namespace SVF;
36
37
  using namespace SVFUtil;
@@ -173,7 +174,7 @@ SVFIR::SVFStmtList& MRGenerator::getPAGEdgesFromInst(const ICFGNode* node)
173
174
  void MRGenerator::collectModRefForLoadStore()
174
175
  {
175
176
 
176
- PTACallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
177
+ CallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
177
178
  for (const auto& item: *svfirCallGraph)
178
179
  {
179
180
  const SVFFunction& fun = *item.second->getFunction();
@@ -31,6 +31,7 @@
31
31
  #include "MSSA/MemPartition.h"
32
32
  #include "MSSA/MemSSA.h"
33
33
  #include "Graphs/SVFGStat.h"
34
+ #include "Graphs/CallGraph.h"
34
35
 
35
36
  using namespace SVF;
36
37
  using namespace SVFUtil;
@@ -575,7 +576,7 @@ u32_t MemSSA::getBBPhiNum() const
575
576
  void MemSSA::dumpMSSA(OutStream& Out)
576
577
  {
577
578
 
578
- PTACallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
579
+ CallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
579
580
  for (const auto& item: *svfirCallGraph)
580
581
  {
581
582
  const SVFFunction* fun = item.second->getFunction();
@@ -33,6 +33,8 @@
33
33
  #include "Graphs/SVFG.h"
34
34
  #include "MSSA/SVFGBuilder.h"
35
35
  #include "WPA/Andersen.h"
36
+ #include "Graphs/CallGraph.h"
37
+
36
38
 
37
39
  using namespace SVF;
38
40
  using namespace SVFUtil;
@@ -101,7 +103,7 @@ std::unique_ptr<MemSSA> SVFGBuilder::buildMSSA(BVDataPTAImpl* pta, bool ptrOnlyM
101
103
 
102
104
  auto mssa = std::make_unique<MemSSA>(pta, ptrOnlyMSSA);
103
105
 
104
- PTACallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
106
+ CallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
105
107
  for (const auto& item: *svfirCallGraph)
106
108
  {
107
109
 
@@ -31,6 +31,7 @@
31
31
  #include "Util/Options.h"
32
32
  #include "MTA/TCT.h"
33
33
  #include "MTA/MTA.h"
34
+ #include "Graphs/CallGraph.h"
34
35
 
35
36
  #include <string>
36
37
 
@@ -185,7 +186,7 @@ void TCT::markRelProcs(const SVFFunction* svffun)
185
186
  */
186
187
  void TCT::collectEntryFunInCallGraph()
187
188
  {
188
- PTACallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
189
+ CallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
189
190
  for (const auto& item: *svfirCallGraph)
190
191
  {
191
192
  const SVFFunction* fun = item.second->getFunction();
@@ -116,8 +116,8 @@ void PointerAnalysis::initialize()
116
116
  }
117
117
  else
118
118
  {
119
- PTACallGraph* cg = pag->getCallGraph();
120
- callgraph = new PTACallGraph(*cg);
119
+ CallGraphBuilder bd;
120
+ callgraph = bd.buildPTACallGraph();
121
121
  }
122
122
  callGraphSCCDetection();
123
123
 
@@ -35,6 +35,7 @@
35
35
  #include <climits>
36
36
  #include <cmath>
37
37
  #include "SVFIR/SVFStatements.h"
38
+ #include "Graphs/CallGraph.h"
38
39
 
39
40
  using namespace SVF;
40
41
  using namespace SVFUtil;
@@ -59,7 +60,7 @@ void SaberCondAllocator::allocate(const SVFModule *M)
59
60
  {
60
61
  DBOUT(DGENERAL, outs() << pasMsg("path condition allocation starts\n"));
61
62
 
62
- PTACallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
63
+ CallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
63
64
  for (const auto& item: *svfirCallGraph)
64
65
  {
65
66
  const SVFFunction *func = (item.second)->getFunction();
@@ -29,6 +29,7 @@
29
29
 
30
30
  #include "Util/Options.h"
31
31
  #include "SVFIR/SVFIR.h"
32
+ #include "Graphs/CallGraph.h"
32
33
 
33
34
  using namespace SVF;
34
35
  using namespace SVFUtil;
@@ -27,7 +27,7 @@
27
27
  * Author: Xiao Cheng
28
28
  */
29
29
  #include "Util/CDGBuilder.h"
30
- #include "Graphs/PTACallGraph.h"
30
+ #include "Graphs/CallGraph.h"
31
31
 
32
32
  using namespace SVF;
33
33
  using namespace SVFUtil;
@@ -123,7 +123,7 @@ s64_t CDGBuilder::getBBSuccessorBranchID(const SVFBasicBlock *BB, const SVFBasic
123
123
  */
124
124
  void CDGBuilder::buildControlDependence(const SVFModule *svfgModule)
125
125
  {
126
- PTACallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
126
+ CallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
127
127
  for (const auto& item: *svfirCallGraph)
128
128
  {
129
129
  const SVFFunction *svfFun = (item.second)->getFunction();
@@ -32,13 +32,15 @@
32
32
  #include "Util/CallGraphBuilder.h"
33
33
  #include "Graphs/ICFG.h"
34
34
  #include "SVFIR/SVFIR.h"
35
+ #include "Graphs/CallGraph.h"
36
+ #include "Graphs/ThreadCallGraph.h"
35
37
 
36
38
  using namespace SVF;
37
39
  using namespace SVFUtil;
38
40
 
39
- PTACallGraph* CallGraphBuilder::buildSVFIRCallGraph(SVFModule* svfModule)
41
+ CallGraph* CallGraphBuilder::buildSVFIRCallGraph(SVFModule* svfModule)
40
42
  {
41
- PTACallGraph* callgraph = new PTACallGraph();
43
+ CallGraph* callgraph = new CallGraph();
42
44
  for (const SVFFunction* svfFunc: svfModule->getFunctionSet())
43
45
  {
44
46
  callgraph->addCallGraphNode(svfFunc);
@@ -64,9 +66,15 @@ PTACallGraph* CallGraphBuilder::buildSVFIRCallGraph(SVFModule* svfModule)
64
66
  return callgraph;
65
67
  }
66
68
 
69
+ PTACallGraph* CallGraphBuilder::buildPTACallGraph()
70
+ {
71
+ CallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
72
+ return new PTACallGraph(*svfirCallGraph);
73
+ }
74
+
67
75
  ThreadCallGraph* CallGraphBuilder::buildThreadCallGraph()
68
76
  {
69
- PTACallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
77
+ CallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
70
78
  ThreadCallGraph* cg = new ThreadCallGraph(*svfirCallGraph);
71
79
 
72
80
  ThreadAPI* tdAPI = ThreadAPI::getThreadAPI();
@@ -29,6 +29,7 @@
29
29
 
30
30
  #include "Util/Options.h"
31
31
  #include "Util/SVFStat.h"
32
+ #include "Graphs/CallGraph.h"
32
33
 
33
34
  using namespace SVF;
34
35
  using namespace std;
@@ -216,7 +217,7 @@ void SVFStat::branchStat()
216
217
  {
217
218
  u32_t numOfBB_2Succ = 0;
218
219
  u32_t numOfBB_3Succ = 0;
219
- PTACallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
220
+ CallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
220
221
  for (const auto& item: *svfirCallGraph)
221
222
  {
222
223
  const SVFFunction* func = item.second->getFunction();
@@ -30,6 +30,7 @@
30
30
  #include "Util/Options.h"
31
31
  #include "Util/SVFUtil.h"
32
32
  #include "MemoryModel/PointsTo.h"
33
+ #include "Graphs/CallGraph.h"
33
34
 
34
35
  #include <sys/resource.h> /// increase stack size
35
36
 
@@ -401,10 +402,10 @@ bool SVFUtil::isProgExitCall(const CallICFGNode* cs)
401
402
  /// Get program entry function from module.
402
403
  const SVFFunction* SVFUtil::getProgFunction(const std::string& funName)
403
404
  {
404
- PTACallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
405
+ CallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
405
406
  for (const auto& item: *svfirCallGraph)
406
407
  {
407
- const PTACallGraphNode*fun = item.second;
408
+ const CallGraphNode*fun = item.second;
408
409
  if (fun->getName()==funName)
409
410
  return fun->getFunction();
410
411
  }
@@ -414,10 +415,10 @@ const SVFFunction* SVFUtil::getProgFunction(const std::string& funName)
414
415
  /// Get program entry function from module.
415
416
  const SVFFunction* SVFUtil::getProgEntryFunction()
416
417
  {
417
- PTACallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
418
+ CallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
418
419
  for (const auto& item: *svfirCallGraph)
419
420
  {
420
- const PTACallGraphNode*fun = item.second;
421
+ const CallGraphNode*fun = item.second;
421
422
  if (isProgEntryFunction(fun->getFunction()))
422
423
  return (fun->getFunction());
423
424
  }
@@ -32,7 +32,7 @@
32
32
 
33
33
  #include "Util/ThreadAPI.h"
34
34
  #include "Util/SVFUtil.h"
35
- #include "Graphs/PTACallGraph.h"
35
+ #include "Graphs/CallGraph.h"
36
36
  #include "SVFIR/SVFIR.h"
37
37
 
38
38
  #include <iostream> /// std output
@@ -270,7 +270,7 @@ void ThreadAPI::performAPIStat(SVFModule* module)
270
270
 
271
271
  statInit(tdAPIStatMap);
272
272
 
273
- PTACallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
273
+ CallGraph* svfirCallGraph = PAG::getPAG()->getCallGraph();
274
274
  for (const auto& item: *svfirCallGraph)
275
275
  {
276
276
  for (SVFFunction::const_iterator bit = (item.second)->getFunction()->begin(), ebit = (item.second)->getFunction()->end(); bit != ebit; ++bit)
@@ -105,7 +105,7 @@ private:
105
105
  InstToBlockNodeMapTy InstToBlockNodeMap; ///< map a basic block to its ICFGNode
106
106
  FunToFunEntryNodeMapTy FunToFunEntryNodeMap; ///< map a function to its FunExitICFGNode
107
107
  FunToFunExitNodeMapTy FunToFunExitNodeMap; ///< map a function to its FunEntryICFGNode
108
- PTACallGraph* callgraph;
108
+ CallGraph* callgraph;
109
109
 
110
110
  /// Constructor
111
111
  LLVMModuleSet();