Static Value-Flow Analysis
PTACallGraph.h
Go to the documentation of this file.
1 //===- PTACallGraph.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  * PTACallGraph.h
25  *
26  * Created on: Nov 7, 2013
27  * Author: Yulei Sui
28  */
29 
30 #ifndef PTACALLGRAPH_H_
31 #define PTACALLGRAPH_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 PTACallGraphNode;
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  */
52 {
53 
54 public:
56  enum CEDGEK
57  {
59  };
60 
61 
62 private:
66 public:
70  {
71  }
74  {
75  }
78  {
79  return (cs << EdgeKindMaskBits) | k;
80  }
82 
83  inline CallSiteID getCallSiteID() const
84  {
85  return csId;
86  }
87  inline bool isDirectCallEdge() const
88  {
89  return !directCalls.empty() && indirectCalls.empty();
90  }
91  inline bool isIndirectCallEdge() const
92  {
93  return directCalls.empty() && !indirectCalls.empty();
94  }
96  {
97  return directCalls;
98  }
100  {
101  return indirectCalls;
102  }
103  inline const CallInstSet& getDirectCalls() const
104  {
105  return directCalls;
106  }
107  inline const CallInstSet& getIndirectCalls() const
108  {
109  return indirectCalls;
110  }
112 
114 
115  void addDirectCallSite(const CallICFGNode* call);
116 
117  void addInDirectCallSite(const CallICFGNode* call);
119 
121 
122  inline CallInstSet::const_iterator directCallsBegin() const
123  {
124  return directCalls.begin();
125  }
126  inline CallInstSet::const_iterator directCallsEnd() const
127  {
128  return directCalls.end();
129  }
130 
131  inline CallInstSet::const_iterator indirectCallsBegin() const
132  {
133  return indirectCalls.begin();
134  }
135  inline CallInstSet::const_iterator indirectCallsEnd() const
136  {
137  return indirectCalls.end();
138  }
140 
142 
143  static inline bool classof(const PTACallGraphEdge*)
144  {
145  return true;
146  }
147  static inline bool classof(const GenericCallGraphEdgeTy *edge)
148  {
149  return edge->getEdgeKind() == PTACallGraphEdge::CallRetEdge ||
152  }
154 
156 
158  {
159  o << edge.toString();
160  return o;
161  }
163 
164  virtual const std::string toString() const;
165 
167 
168 };
169 
170 /*
171  * Call Graph node representing a function
172  */
175 {
176 
177 public:
179  typedef PTACallGraphEdge::CallGraphEdgeSet::iterator iterator;
180  typedef PTACallGraphEdge::CallGraphEdgeSet::const_iterator const_iterator;
181 
182 private:
183  const SVFFunction* fun;
184 
185 public:
188  {
189 
190  }
191 
192  inline const std::string &getName() const
193  {
194  return fun->getName();
195  }
196 
198  inline const SVFFunction* getFunction() const
199  {
200  return fun;
201  }
202 
204  bool isReachableFromProgEntry() const;
205 
206 
208 
210  {
211  o << node.toString();
212  return o;
213  }
215 
216  virtual const std::string toString() const;
217 
219 
220  static inline bool classof(const PTACallGraphNode*)
221  {
222  return true;
223  }
224 
225  static inline bool classof(const GenericICFGNodeTy* node)
226  {
227  return node->getNodeKind() == CallNodeKd;
228  }
229 
230  static inline bool classof(const SVFBaseNode* node)
231  {
232  return node->getNodeKind() == CallNodeKd;
233  }
235 };
236 
242 {
243 
244 public:
248  typedef std::pair<const CallICFGNode*, const SVFFunction*> CallSitePair;
253  typedef CallGraphEdgeSet::iterator CallGraphEdgeIter;
254  typedef CallGraphEdgeSet::const_iterator CallGraphEdgeConstIter;
255 
256  enum CGEK
257  {
259  };
260 
261 private:
264 
269 
270 protected:
273 
277 
279  void destroy();
280 
281 public:
284 
286  PTACallGraph(const PTACallGraph& other);
287 
288  void addCallGraphNode(const SVFFunction* fun);
289 
291  virtual ~PTACallGraph()
292  {
293  destroy();
294  }
295 
297  inline CGEK getKind() const
298  {
299  return kind;
300  }
301 
303 
305  {
306  return indirectCallMap;
307  }
308  inline bool hasIndCSCallees(const CallICFGNode* cs) const
309  {
310  return (indirectCallMap.find(cs) != indirectCallMap.end());
311  }
312  inline const FunctionSet& getIndCSCallees(const CallICFGNode* cs) const
313  {
314  CallEdgeMap::const_iterator it = indirectCallMap.find(cs);
315  assert(it!=indirectCallMap.end() && "not an indirect callsite!");
316  return it->second;
317  }
320  {
321  return totalCallSiteNum;
322  }
323 
325  {
327  }
328 
330  {
332  }
333 
335  void verifyCallGraph();
336 
338 
340  {
341  return getGNode(id);
342  }
344  {
345  FunToCallGraphNodeMap::const_iterator it = funToCallGraphNodeMap.find(fun);
346  assert(it!=funToCallGraphNodeMap.end() && "call graph node not found!!");
347  return it->second;
348  }
349 
351 
353 
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  {
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  inline CallSiteID getCallSiteID(const CallICFGNode* cs, const SVFFunction* callee) const
369  {
370  CallSitePair newCS(std::make_pair(cs, callee));
371  CallSiteToIdMap::const_iterator it = csToIdMap.find(newCS);
372  assert(it != csToIdMap.end() && "callsite id not found! This maybe a partially resolved callgraph, please check the indCallEdge limit");
373  return it->second;
374  }
375  inline bool hasCallSiteID(const CallICFGNode* cs, const SVFFunction* callee) const
376  {
377  CallSitePair newCS(std::make_pair(cs, callee));
378  CallSiteToIdMap::const_iterator it = csToIdMap.find(newCS);
379  return it != csToIdMap.end();
380  }
381  inline const CallSitePair& getCallSitePair(CallSiteID id) const
382  {
383  IdToCallSiteMap::const_iterator it = idToCSMap.find(id);
384  assert(it != idToCSMap.end() && "cannot find call site for this CallSiteID");
385  return (it->second);
386  }
387  inline const CallICFGNode* getCallSite(CallSiteID id) const
388  {
389  return getCallSitePair(id).first;
390  }
392  {
393  return getCallSite(id)->getCaller();
394  }
396  {
397  return getCallSitePair(id).second;
398  }
406 
408  inline void getCallees(const CallICFGNode* cs, FunctionSet& callees)
409  {
410  if(hasCallGraphEdge(cs))
411  {
412  for (CallGraphEdgeSet::const_iterator it = getCallEdgeBegin(cs), eit =
413  getCallEdgeEnd(cs); it != eit; ++it)
414  {
415  callees.insert((*it)->getDstNode()->getFunction());
416  }
417  }
418  }
419 
421 
422  inline bool hasCallGraphEdge(const CallICFGNode* inst) const
424  {
426  }
427  inline CallGraphEdgeSet::const_iterator getCallEdgeBegin(const CallICFGNode* inst) const
428  {
429  CallInstToCallGraphEdgesMap::const_iterator it = callinstToCallGraphEdgesMap.find(inst);
430  assert(it!=callinstToCallGraphEdgesMap.end()
431  && "call instruction does not have a valid callee");
432  return it->second.begin();
433  }
434  inline CallGraphEdgeSet::const_iterator getCallEdgeEnd(const CallICFGNode* inst) const
435  {
436  CallInstToCallGraphEdgesMap::const_iterator it = callinstToCallGraphEdgesMap.find(inst);
437  assert(it!=callinstToCallGraphEdgesMap.end()
438  && "call instruction does not have a valid callee");
439  return it->second.end();
440  }
442  inline void addEdge(PTACallGraphEdge* edge)
444  {
445  edge->getDstNode()->addIncomingEdge(edge);
446  edge->getSrcNode()->addOutgoingEdge(edge);
447  }
448 
450 
451  void addDirectCallGraphEdge(const CallICFGNode* call, const SVFFunction* callerFun, const SVFFunction* calleeFun);
452  void addIndirectCallGraphEdge(const CallICFGNode* cs,const SVFFunction* callerFun, const SVFFunction* calleeFun);
454 
456 
457  void getAllCallSitesInvokingCallee(const SVFFunction* callee, PTACallGraphEdge::CallInstSet& csSet);
458  void getDirCallSitesInvokingCallee(const SVFFunction* callee, PTACallGraphEdge::CallInstSet& csSet);
459  void getIndCallSitesInvokingCallee(const SVFFunction* callee, PTACallGraphEdge::CallInstSet& csSet);
461 
463  bool isReachableBetweenFunctions(const SVFFunction* srcFn, const SVFFunction* dstFn) const;
464 
466  void dump(const std::string& filename);
467 
469  void view();
470 };
471 
472 } // End namespace SVF
473 
474 namespace SVF
475 {
476 /* !
477  * GenericGraphTraits specializations for generic graph algorithms.
478  * Provide graph traits for traversing from a constraint node using standard graph traversals.
479  */
480 template<> struct GenericGraphTraits<SVF::PTACallGraphNode*> : public GenericGraphTraits<SVF::GenericNode<SVF::PTACallGraphNode,SVF::PTACallGraphEdge>* >
481 {
482 };
483 
485 template<>
486 struct GenericGraphTraits<Inverse<SVF::PTACallGraphNode*> > : public GenericGraphTraits<Inverse<SVF::GenericNode<SVF::PTACallGraphNode,SVF::PTACallGraphEdge>* > >
487 {
488 };
489 
490 template<> struct GenericGraphTraits<SVF::PTACallGraph*> : public GenericGraphTraits<SVF::GenericGraph<SVF::PTACallGraphNode,SVF::PTACallGraphEdge>* >
491 {
493 };
494 
495 } // End namespace llvm
496 
497 #endif /* CALLGRAPH_H_ */
const char *const string
Definition: cJSON.h:172
const SVFFunction * getCaller() const
Return callsite.
Definition: ICFGNode.h:470
NodeType * getSrcNode() const
Definition: GenericGraph.h:97
GEdgeKind getEdgeKind() const
Definition: GenericGraph.h:89
NodeType * getDstNode() const
Definition: GenericGraph.h:101
static constexpr unsigned char EdgeKindMaskBits
We use the lower 8 bits to denote edge kind.
Definition: GenericGraph.h:132
NodeType * getGNode(NodeID id) const
Get a node.
Definition: GenericGraph.h:653
OrderedSet< EdgeType *, typename EdgeType::equalGEdge > GEdgeSetTy
Edge kind.
Definition: GenericGraph.h:402
virtual const std::string toString() const
friend OutStream & operator<<(OutStream &o, const PTACallGraphEdge &edge)
Overloading operator << for dumping ICFG node ID.
Definition: PTACallGraph.h:157
CallInstSet directCalls
Definition: PTACallGraph.h:63
CallInstSet::const_iterator indirectCallsEnd() const
Definition: PTACallGraph.h:135
static GEdgeFlag makeEdgeFlagWithInvokeID(GEdgeKind k, CallSiteID cs)
Compute the unique edgeFlag value from edge kind and CallSiteID.
Definition: PTACallGraph.h:77
const CallInstSet & getIndirectCalls() const
Definition: PTACallGraph.h:107
const CallInstSet & getDirectCalls() const
Definition: PTACallGraph.h:103
CallInstSet indirectCalls
Definition: PTACallGraph.h:64
bool isIndirectCallEdge() const
Definition: PTACallGraph.h:91
CallInstSet::const_iterator directCallsBegin() const
Iterators for direct and indirect callsites.
Definition: PTACallGraph.h:122
CallInstSet & getIndirectCalls()
Definition: PTACallGraph.h:99
GenericNode< PTACallGraphNode, PTACallGraphEdge >::GEdgeSetTy CallGraphEdgeSet
Definition: PTACallGraph.h:166
bool isDirectCallEdge() const
Definition: PTACallGraph.h:87
void addDirectCallSite(const CallICFGNode *call)
Add direct and indirect callsite.
PTACallGraphEdge(PTACallGraphNode *s, PTACallGraphNode *d, CEDGEK kind, CallSiteID cs)
Constructor.
Definition: PTACallGraph.h:68
CallInstSet::const_iterator directCallsEnd() const
Definition: PTACallGraph.h:126
void addInDirectCallSite(const CallICFGNode *call)
static bool classof(const PTACallGraphEdge *)
ClassOf.
Definition: PTACallGraph.h:143
Set< const CallICFGNode * > CallInstSet
Definition: PTACallGraph.h:55
CallInstSet & getDirectCalls()
Definition: PTACallGraph.h:95
virtual ~PTACallGraphEdge()
Destructor.
Definition: PTACallGraph.h:73
CallSiteID getCallSiteID() const
Get direct and indirect calls.
Definition: PTACallGraph.h:83
static bool classof(const GenericCallGraphEdgeTy *edge)
Definition: PTACallGraph.h:147
CallInstSet::const_iterator indirectCallsBegin() const
Definition: PTACallGraph.h:131
const SVFFunction * fun
Definition: PTACallGraph.h:183
static bool classof(const SVFBaseNode *node)
Definition: PTACallGraph.h:230
friend OutStream & operator<<(OutStream &o, const PTACallGraphNode &node)
Overloading operator << for dumping ICFG node ID.
Definition: PTACallGraph.h:209
const std::string & getName() const
Definition: PTACallGraph.h:192
virtual const std::string toString() const
PTACallGraphEdge::CallGraphEdgeSet::iterator iterator
Definition: PTACallGraph.h:179
static bool classof(const GenericICFGNodeTy *node)
Definition: PTACallGraph.h:225
const SVFFunction * getFunction() const
Get function of this call node.
Definition: PTACallGraph.h:198
PTACallGraphEdge::CallGraphEdgeSet CallGraphEdgeSet
Definition: PTACallGraph.h:178
static bool classof(const PTACallGraphNode *)
Methods for support type inquiry through isa, cast, and dyn_cast:
Definition: PTACallGraph.h:220
PTACallGraphEdge::CallGraphEdgeSet::const_iterator const_iterator
Definition: PTACallGraph.h:180
bool isReachableFromProgEntry() const
Return TRUE if this function can be reached from main.
PTACallGraphNode(NodeID i, const SVFFunction *f)
Constructor.
Definition: PTACallGraph.h:187
Map< const CallICFGNode *, CallGraphEdgeSet > CallInstToCallGraphEdgesMap
Definition: PTACallGraph.h:247
void getDirCallSitesInvokingCallee(const SVFFunction *callee, PTACallGraphEdge::CallInstSet &csSet)
u32_t getNumOfResolvedIndCallEdge() const
Definition: PTACallGraph.h:324
const CallICFGNode * getCallSite(CallSiteID id) const
Definition: PTACallGraph.h:387
CallGraphEdgeSet::const_iterator getCallEdgeEnd(const CallICFGNode *inst) const
Definition: PTACallGraph.h:434
std::pair< const CallICFGNode *, const SVFFunction * > CallSitePair
Definition: PTACallGraph.h:248
PTACallGraphEdge::CallGraphEdgeSet CallGraphEdgeSet
Definition: PTACallGraph.h:245
PTACallGraphEdge * getGraphEdge(PTACallGraphNode *src, PTACallGraphNode *dst, PTACallGraphEdge::CEDGEK kind, CallSiteID csId)
Get call graph edge via nodes.
static CallSiteID totalCallSiteNum
CallSiteIDs, start from 1;.
Definition: PTACallGraph.h:268
CallGraphEdgeSet::iterator CallGraphEdgeIter
Definition: PTACallGraph.h:253
void addEdge(PTACallGraphEdge *edge)
Add call graph edge.
Definition: PTACallGraph.h:443
void getCallees(const CallICFGNode *cs, FunctionSet &callees)
Get all callees for a callsite.
Definition: PTACallGraph.h:408
const CallInstToCallGraphEdgesMap & getCallInstToCallGraphEdgesMap() const
Definition: PTACallGraph.h:329
const SVFFunction * getCallerOfCallSite(CallSiteID id) const
Definition: PTACallGraph.h:391
void addIndirectCallGraphEdge(const CallICFGNode *cs, const SVFFunction *callerFun, const SVFFunction *calleeFun)
OrderedMap< const CallICFGNode *, FunctionSet > CallEdgeMap
Definition: PTACallGraph.h:252
CallGraphEdgeSet::const_iterator getCallEdgeBegin(const CallICFGNode *inst) const
Definition: PTACallGraph.h:427
static IdToCallSiteMap idToCSMap
Map a callsite ID to a pair of call instruction and callee.
Definition: PTACallGraph.h:267
Set< const SVFFunction * > FunctionSet
Definition: PTACallGraph.h:251
Map< CallSiteID, CallSitePair > IdToCallSiteMap
Definition: PTACallGraph.h:250
PTACallGraph(CGEK k=NormCallGraph)
Constructor.
void addDirectCallGraphEdge(const CallICFGNode *call, const SVFFunction *callerFun, const SVFFunction *calleeFun)
Add direct/indirect call edges.
void destroy()
Clean up memory.
PTACallGraphEdge * hasGraphEdge(PTACallGraphNode *src, PTACallGraphNode *dst, PTACallGraphEdge::CEDGEK kind, CallSiteID csId) const
Whether we have already created this call graph edge.
CallSiteID getCallSiteID(const CallICFGNode *cs, const SVFFunction *callee) const
Definition: PTACallGraph.h:368
bool hasIndCSCallees(const CallICFGNode *cs) const
Definition: PTACallGraph.h:308
static CallSiteToIdMap csToIdMap
Call site information.
Definition: PTACallGraph.h:266
void view()
View the graph from the debugger.
virtual ~PTACallGraph()
Destructor.
Definition: PTACallGraph.h:291
void getAllCallSitesInvokingCallee(const SVFFunction *callee, PTACallGraphEdge::CallInstSet &csSet)
Get callsites invoking the callee.
void dump(const std::string &filename)
Dump the graph.
void addCallGraphNode(const SVFFunction *fun)
const CallSitePair & getCallSitePair(CallSiteID id) const
Definition: PTACallGraph.h:381
CallSiteID addCallSite(const CallICFGNode *cs, const SVFFunction *callee)
Add/Get CallSiteID.
Definition: PTACallGraph.h:354
FunToCallGraphNodeMap funToCallGraphNodeMap
Call Graph node map.
Definition: PTACallGraph.h:271
void getIndCallSitesInvokingCallee(const SVFFunction *callee, PTACallGraphEdge::CallInstSet &csSet)
CallGraphEdgeSet::const_iterator CallGraphEdgeConstIter
Definition: PTACallGraph.h:254
Map< const SVFFunction *, PTACallGraphNode * > FunToCallGraphNodeMap
Definition: PTACallGraph.h:246
bool isReachableBetweenFunctions(const SVFFunction *srcFn, const SVFFunction *dstFn) const
Whether its reachable between two functions.
bool hasCallSiteID(const CallICFGNode *cs, const SVFFunction *callee) const
Definition: PTACallGraph.h:375
PTACallGraphNode * getCallGraphNode(NodeID id) const
Get call graph node.
Definition: PTACallGraph.h:339
u32_t getTotalCallSiteNumber() const
Definition: PTACallGraph.h:319
const SVFFunction * getCalleeOfCallSite(CallSiteID id) const
Definition: PTACallGraph.h:395
CallInstToCallGraphEdgesMap callinstToCallGraphEdgesMap
Map a call instruction to its corresponding call edges.
Definition: PTACallGraph.h:272
const FunctionSet & getIndCSCallees(const CallICFGNode *cs) const
Definition: PTACallGraph.h:312
void verifyCallGraph()
Issue a warning if the function which has indirect call sites can not be reached from program entry.
CGEK getKind() const
Return type of this callgraph.
Definition: PTACallGraph.h:297
CallEdgeMap & getIndCallMap()
Get callees from an indirect callsite.
Definition: PTACallGraph.h:304
CallEdgeMap indirectCallMap
Indirect call map.
Definition: PTACallGraph.h:263
u32_t numOfResolvedIndCallEdge
Definition: PTACallGraph.h:275
PTACallGraphNode * getCallGraphNode(const SVFFunction *fun) const
Definition: PTACallGraph.h:343
Map< CallSitePair, CallSiteID > CallSiteToIdMap
Definition: PTACallGraph.h:249
bool hasCallGraphEdge(const CallICFGNode *inst) const
Get call graph edge via call instruction.
Definition: PTACallGraph.h:423
GNodeK getNodeKind() const
Get node kind.
Definition: GenericGraph.h:266
const std::string & getName() const
Definition: SVFValue.h:243
for isBitcode
Definition: BasicTypes.h:68
unsigned CallSiteID
Definition: GeneralType.h:58
u32_t NodeID
Definition: GeneralType.h:55
GenericNode< PTACallGraphNode, PTACallGraphEdge > GenericCallGraphNodeTy
Definition: PTACallGraph.h:173
GenericGraph< PTACallGraphNode, PTACallGraphEdge > GenericCallGraphTy
Definition: PTACallGraph.h:240
std::unordered_map< Key, Value, Hash, KeyEqual, Allocator > Map
Definition: GeneralType.h:101
std::ostream OutStream
Definition: GeneralType.h:45
GenericEdge< PTACallGraphNode > GenericCallGraphEdgeTy
Definition: PTACallGraph.h:42
unsigned u32_t
Definition: GeneralType.h:46
std::map< Key, Value, Compare, Allocator > OrderedMap
Definition: GeneralType.h:109
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set
Definition: GeneralType.h:96