Static Value-Flow Analysis
Loading...
Searching...
No Matches
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
38namespace SVF
39{
40
41class PTACallGraphNode;
42class SVFModule;
43class CallGraph;
44
45
46/*
47 * Call Graph edge representing a calling relation between two functions
48 * Multiple calls from function A to B are merged into one call edge
49 * Each call edge has a set of direct callsites and a set of indirect callsites
50 */
53{
54
55public:
61
62
63private:
67public:
75 {
76 }
79 {
80 return (cs << EdgeKindMaskBits) | k;
81 }
83
85 {
86 return csId;
87 }
88 inline bool isDirectCallEdge() const
89 {
90 return !directCalls.empty() && indirectCalls.empty();
91 }
92 inline bool isIndirectCallEdge() const
93 {
94 return directCalls.empty() && !indirectCalls.empty();
95 }
97 {
98 return directCalls;
99 }
101 {
102 return indirectCalls;
103 }
104 inline const CallInstSet& getDirectCalls() const
105 {
106 return directCalls;
107 }
108 inline const CallInstSet& getIndirectCalls() const
109 {
110 return indirectCalls;
111 }
113
115
116 void addDirectCallSite(const CallICFGNode* call);
117
118 void addInDirectCallSite(const CallICFGNode* call);
120
122
123 inline CallInstSet::const_iterator directCallsBegin() const
124 {
125 return directCalls.begin();
126 }
127 inline CallInstSet::const_iterator directCallsEnd() const
128 {
129 return directCalls.end();
130 }
131
132 inline CallInstSet::const_iterator indirectCallsBegin() const
133 {
134 return indirectCalls.begin();
135 }
136 inline CallInstSet::const_iterator indirectCallsEnd() const
137 {
138 return indirectCalls.end();
139 }
141
143
144 static inline bool classof(const PTACallGraphEdge*)
145 {
146 return true;
147 }
148 static inline bool classof(const GenericPTACallGraphEdgeTy *edge)
149 {
150 return edge->getEdgeKind() == PTACallGraphEdge::CallRetEdge ||
151 edge->getEdgeKind() == PTACallGraphEdge::TDForkEdge ||
152 edge->getEdgeKind() == PTACallGraphEdge::TDJoinEdge;
153 }
155
157
159 {
160 o << edge.toString();
161 return o;
162 }
164
165 virtual const std::string toString() const;
166
168
169};
170
171/*
172 * Call Graph node representing a function
173 */
176{
177private:
179
180public:
186
187 inline const std::string &getName() const
188 {
189 return fun->getName();
190 }
191
193 inline const SVFFunction* getFunction() const
194 {
195 return fun;
196 }
197
199 bool isReachableFromProgEntry() const;
200
201
203
205 {
206 o << node.toString();
207 return o;
208 }
210
211 virtual const std::string toString() const;
212
214
215 static inline bool classof(const PTACallGraphNode*)
216 {
217 return true;
218 }
219
220 static inline bool classof(const GenericICFGNodeTy* node)
221 {
222 return node->getNodeKind() == CallNodeKd;
223 }
224
225 static inline bool classof(const SVFBaseNode* node)
226 {
227 return node->getNodeKind() == CallNodeKd;
228 }
230};
231
237{
238
239public:
243 typedef std::pair<const CallICFGNode*, const SVFFunction*> CallSitePair;
248 typedef CallGraphEdgeSet::iterator CallGraphEdgeIter;
249 typedef CallGraphEdgeSet::const_iterator CallGraphEdgeConstIter;
250
255
256private:
259
264
265protected:
268
272
274 void destroy();
275
276protected:
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 {
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
295 {
296 edge->getDstNode()->addIncomingEdge(edge);
297 edge->getSrcNode()->addOutgoingEdge(edge);
298 }
299
300public:
303
306
309 {
310 destroy();
311 }
312
314 inline CGEK getKind() const
315 {
316 return kind;
317 }
318
320
322 {
323 return indirectCallMap;
324 }
325 inline bool hasIndCSCallees(const CallICFGNode* cs) const
326 {
327 return (indirectCallMap.find(cs) != indirectCallMap.end());
328 }
329 inline const FunctionSet& getIndCSCallees(const CallICFGNode* cs) const
330 {
331 CallEdgeMap::const_iterator it = indirectCallMap.find(cs);
332 assert(it!=indirectCallMap.end() && "not an indirect callsite!");
333 return it->second;
334 }
337 {
338 return totalCallSiteNum;
339 }
340
342 {
344 }
345
350
352 void verifyCallGraph();
353
355
357 {
358 return getGNode(id);
359 }
361 {
362 FunToCallGraphNodeMap::const_iterator it = funToCallGraphNodeMap.find(fun);
363 assert(it!=funToCallGraphNodeMap.end() && "call graph node not found!!");
364 return it->second;
365 }
366
368
370
372 {
373 CallSitePair newCS(std::make_pair(cs, callee));
374 CallSiteToIdMap::const_iterator it = csToIdMap.find(newCS);
375 assert(it != csToIdMap.end() && "callsite id not found! This maybe a partially resolved callgraph, please check the indCallEdge limit");
376 return it->second;
377 }
378 inline bool hasCallSiteID(const CallICFGNode* cs, const SVFFunction* callee) const
379 {
380 CallSitePair newCS(std::make_pair(cs, callee));
381 CallSiteToIdMap::const_iterator it = csToIdMap.find(newCS);
382 return it != csToIdMap.end();
383 }
385 {
386 IdToCallSiteMap::const_iterator it = idToCSMap.find(id);
387 assert(it != idToCSMap.end() && "cannot find call site for this CallSiteID");
388 return (it->second);
389 }
390 inline const CallICFGNode* getCallSite(CallSiteID id) const
391 {
392 return getCallSitePair(id).first;
393 }
395 {
396 return getCallSite(id)->getCaller();
397 }
399 {
400 return getCallSitePair(id).second;
401 }
403
409
412 {
413 if(hasCallGraphEdge(cs))
414 {
415 for (CallGraphEdgeSet::const_iterator it = getCallEdgeBegin(cs), eit =
416 getCallEdgeEnd(cs); it != eit; ++it)
417 {
418 callees.insert((*it)->getDstNode()->getFunction());
419 }
420 }
421 }
422
424
425
426 inline bool hasCallGraphEdge(const CallICFGNode* inst) const
427 {
429 }
430 inline CallGraphEdgeSet::const_iterator getCallEdgeBegin(const CallICFGNode* inst) const
431 {
432 CallInstToCallGraphEdgesMap::const_iterator it = callinstToCallGraphEdgesMap.find(inst);
434 && "call instruction does not have a valid callee");
435 return it->second.begin();
436 }
437 inline CallGraphEdgeSet::const_iterator getCallEdgeEnd(const CallICFGNode* inst) const
438 {
439 CallInstToCallGraphEdgesMap::const_iterator it = callinstToCallGraphEdgesMap.find(inst);
441 && "call instruction does not have a valid callee");
442 return it->second.end();
443 }
445
446
448
451
453
458
461
463 void dump(const std::string& filename);
464
466 void view();
467};
468
469} // End namespace SVF
470
471namespace SVF
472{
473/* !
474 * GenericGraphTraits specializations for generic graph algorithms.
475 * Provide graph traits for traversing from a constraint node using standard graph traversals.
476 */
477template<> struct GenericGraphTraits<SVF::PTACallGraphNode*> : public GenericGraphTraits<SVF::GenericNode<SVF::PTACallGraphNode,SVF::PTACallGraphEdge>* >
478{
479};
480
482template<>
483struct GenericGraphTraits<Inverse<SVF::PTACallGraphNode*> > : public GenericGraphTraits<Inverse<SVF::GenericNode<SVF::PTACallGraphNode,SVF::PTACallGraphEdge>* > >
484{
485};
486
487template<> struct GenericGraphTraits<SVF::PTACallGraph*> : public GenericGraphTraits<SVF::GenericGraph<SVF::PTACallGraphNode,SVF::PTACallGraphEdge>* >
488{
490};
491
492} // End namespace llvm
493
494#endif /* PTACALLGRAPH_H_ */
const SVFFunction * getCaller() const
Return callsite.
Definition ICFGNode.h:470
static constexpr unsigned char EdgeKindMaskBits
We use the lower 8 bits to denote edge kind.
NodeType * getGNode(NodeID id) const
Get a node.
OrderedSet< EdgeType *, typename EdgeType::equalGEdge > GEdgeSetTy
Edge kind.
CallInstSet & getIndirectCalls()
virtual const std::string toString() const
CallInstSet directCalls
CallInstSet::const_iterator indirectCallsEnd() const
static GEdgeFlag makeEdgeFlagWithInvokeID(GEdgeKind k, CallSiteID cs)
Compute the unique edgeFlag value from edge kind and CallSiteID.
CallInstSet indirectCalls
const CallInstSet & getIndirectCalls() const
bool isIndirectCallEdge() const
CallInstSet::const_iterator directCallsBegin() const
Iterators for direct and indirect callsites.
CallInstSet & getDirectCalls()
friend OutStream & operator<<(OutStream &o, const PTACallGraphEdge &edge)
Overloading operator << for dumping ICFG node ID.
bool isDirectCallEdge() const
void addDirectCallSite(const CallICFGNode *call)
Add direct and indirect callsite.
PTACallGraphEdge(PTACallGraphNode *s, PTACallGraphNode *d, CEDGEK kind, CallSiteID cs)
Constructor.
GenericNode< PTACallGraphNode, PTACallGraphEdge >::GEdgeSetTy CallGraphEdgeSet
const CallInstSet & getDirectCalls() const
CallInstSet::const_iterator directCallsEnd() const
void addInDirectCallSite(const CallICFGNode *call)
static bool classof(const PTACallGraphEdge *)
ClassOf.
Set< const CallICFGNode * > CallInstSet
static bool classof(const GenericPTACallGraphEdgeTy *edge)
virtual ~PTACallGraphEdge()
Destructor.
CallSiteID getCallSiteID() const
Get direct and indirect calls.
CallInstSet::const_iterator indirectCallsBegin() const
const SVFFunction * getFunction() const
Get function of this call node.
const SVFFunction * fun
static bool classof(const SVFBaseNode *node)
friend OutStream & operator<<(OutStream &o, const PTACallGraphNode &node)
Overloading operator << for dumping ICFG node ID.
virtual const std::string toString() const
static bool classof(const GenericICFGNodeTy *node)
const std::string & getName() const
static bool classof(const PTACallGraphNode *)
Methods for support type inquiry through isa, cast, and dyn_cast:
bool isReachableFromProgEntry() const
Return TRUE if this function can be reached from main.
PTACallGraphNode(NodeID i, const SVFFunction *f)
Constructor.
Map< const CallICFGNode *, CallGraphEdgeSet > CallInstToCallGraphEdgesMap
void getDirCallSitesInvokingCallee(const SVFFunction *callee, PTACallGraphEdge::CallInstSet &csSet)
const CallICFGNode * getCallSite(CallSiteID id) const
u32_t getNumOfResolvedIndCallEdge() const
CallGraphEdgeSet::const_iterator getCallEdgeEnd(const CallICFGNode *inst) const
std::pair< const CallICFGNode *, const SVFFunction * > CallSitePair
PTACallGraphEdge::CallGraphEdgeSet CallGraphEdgeSet
PTACallGraphEdge * getGraphEdge(PTACallGraphNode *src, PTACallGraphNode *dst, PTACallGraphEdge::CEDGEK kind, CallSiteID csId)
Get call graph edge via nodes.
const FunctionSet & getIndCSCallees(const CallICFGNode *cs) const
static CallSiteID totalCallSiteNum
CallSiteIDs, start from 1;.
CallGraphEdgeSet::iterator CallGraphEdgeIter
void addEdge(PTACallGraphEdge *edge)
Add call graph edge.
void getCallees(const CallICFGNode *cs, FunctionSet &callees)
Get all callees for a callsite.
CallEdgeMap & getIndCallMap()
Get callees from an indirect callsite.
const CallInstToCallGraphEdgesMap & getCallInstToCallGraphEdgesMap() const
void addIndirectCallGraphEdge(const CallICFGNode *cs, const SVFFunction *callerFun, const SVFFunction *calleeFun)
Add indirect call edges.
OrderedMap< const CallICFGNode *, FunctionSet > CallEdgeMap
const SVFFunction * getCallerOfCallSite(CallSiteID id) const
CallGraphEdgeSet::const_iterator getCallEdgeBegin(const CallICFGNode *inst) const
static IdToCallSiteMap idToCSMap
Map a callsite ID to a pair of call instruction and callee.
Set< const SVFFunction * > FunctionSet
Map< CallSiteID, CallSitePair > IdToCallSiteMap
void destroy()
Clean up memory.
const CallSitePair & getCallSitePair(CallSiteID id) const
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
Get CallSiteID.
bool hasIndCSCallees(const CallICFGNode *cs) const
static CallSiteToIdMap csToIdMap
Call site information.
void view()
View the graph from the debugger.
virtual ~PTACallGraph()
Destructor.
void getAllCallSitesInvokingCallee(const SVFFunction *callee, PTACallGraphEdge::CallInstSet &csSet)
Get callsites invoking the callee.
void dump(const std::string &filename)
Dump the graph.
CallSiteID addCallSite(const CallICFGNode *cs, const SVFFunction *callee)
Add CallSiteID.
FunToCallGraphNodeMap funToCallGraphNodeMap
Call Graph node map.
PTACallGraphNode * getCallGraphNode(const SVFFunction *fun) const
void getIndCallSitesInvokingCallee(const SVFFunction *callee, PTACallGraphEdge::CallInstSet &csSet)
CallGraphEdgeSet::const_iterator CallGraphEdgeConstIter
Map< const SVFFunction *, PTACallGraphNode * > FunToCallGraphNodeMap
bool isReachableBetweenFunctions(const SVFFunction *srcFn, const SVFFunction *dstFn) const
Whether its reachable between two functions.
const SVFFunction * getCalleeOfCallSite(CallSiteID id) const
bool hasCallSiteID(const CallICFGNode *cs, const SVFFunction *callee) const
u32_t getTotalCallSiteNumber() const
CallInstToCallGraphEdgesMap callinstToCallGraphEdgesMap
Map a call instruction to its corresponding call edges.
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.
CallEdgeMap indirectCallMap
Indirect call map.
u32_t numOfResolvedIndCallEdge
Map< CallSitePair, CallSiteID > CallSiteToIdMap
PTACallGraphNode * getCallGraphNode(NodeID id) const
Get call graph node.
bool hasCallGraphEdge(const CallICFGNode *inst) const
Get call graph edge via call instruction.
GNodeK getNodeKind() const
Get node kind.
const std::string & getName() const
Definition SVFValue.h:243
for isBitcode
Definition BasicTypes.h:68
unsigned CallSiteID
Definition GeneralType.h:58
GenericEdge< PTACallGraphNode > GenericPTACallGraphEdgeTy
GenericGraph< PTACallGraphNode, PTACallGraphEdge > GenericPTACallGraphTy
u32_t NodeID
Definition GeneralType.h:55
GenericNode< PTACallGraphNode, PTACallGraphEdge > GenericPTACallGraphNodeTy
std::ostream OutStream
Definition GeneralType.h:45
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74
unsigned u32_t
Definition GeneralType.h:46