Static Value-Flow Analysis
Loading...
Searching...
No Matches
CallGraph.cpp
Go to the documentation of this file.
1//===- PTACallGraph.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 * PTACallGraph.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 "Util/Options.h"
34#include "Util/SVFUtil.h"
35#include <sstream>
36#include "Util/Options.h"
37
38using namespace SVF;
39using namespace SVFUtil;
40
44
45
46const std::string &CallGraphNode::getName() const
47{
48 return fun->getName();
49}
50
51
53
55{
56 assert(call->getCalledFunction() && "not a direct callsite??");
57 directCalls.insert(call);
58}
59
61{
62 assert((nullptr == call->getCalledFunction() || !SVFUtil::isa<FunValVar>(SVFUtil::getForkedFun(call))) &&
63 "not an indirect callsite??");
64 indirectCalls.insert(call);
65}
67
68const std::string CallGraphEdge::toString() const
69{
70 std::string str;
71 std::stringstream rawstr(str);
72 rawstr << "CallSite ID: " << getCallSiteID();
74 rawstr << "direct call";
75 else
76 rawstr << "indirect call";
77 rawstr << "[" << getDstID() << "<--" << getSrcID() << "]\t";
78 return rawstr.str();
79}
80
81const std::string CallGraphNode::toString() const
82{
83 std::string str;
84 std::stringstream rawstr(str);
85 rawstr << "CallGraphNode ID: " << getId() << " {fun: " << fun->getName() << "}";
86 return rawstr.str();
87}
88
90{
91 return getCallSite(id)->getCaller();
92}
93
95{
96 std::function<bool(const CallGraphNode*)> dfs =
98 {
99 NodeID id = v->getId();
100 if (!visitedNodes.test_and_set(id))
101 return reachableFromEntry[id];
102
103 if (SVFUtil::isProgEntryFunction(v->getFunction()))
104 return reachableFromEntry[id] = true;
105
106 bool result = false;
107 for (const_iterator it = v->InEdgeBegin(), eit = v->InEdgeEnd(); it != eit; ++it)
108 {
110 result |= dfs(edge->getSrcNode());
111 if (result)
112 break;
113 }
114 return reachableFromEntry[id] = result;
115 };
116
117 return dfs(this);
118}
119
120
127
130{
131 callGraphNodeNum = other.getTotalNodeNum();
134
136 for (const auto& item : other)
137 {
138 const CallGraphNode* cgn = item.second;
139 CallGraphNode* callGraphNode = new CallGraphNode(cgn->getId(), cgn->getFunction());
140 addGNode(cgn->getId(),callGraphNode);
141 funToCallGraphNodeMap[cgn->getFunction()] = callGraphNode;
142 }
143
145 for (const auto& item : other.callinstToCallGraphEdgesMap)
146 {
147 const CallICFGNode* cs = item.first;
148 for (const CallGraphEdge* edge : item.second)
149 {
150 CallGraphNode* src = getCallGraphNode(edge->getSrcID());
151 CallGraphNode* dst = getCallGraphNode(edge->getDstID());
152 CallSiteID csId = addCallSite(cs, dst->getFunction());
153
155 newEdge->addDirectCallSite(cs);
158 }
159 }
160
161}
162
163CallSiteID CallGraph::addCallSite(const CallICFGNode* cs, const FunObjVar* callee, const CallSiteID csid, std::pair<const CallICFGNode*, const FunObjVar*> newCS)
164{
165 csToIdMap.insert(std::make_pair(newCS, csid));
166 idToCSMap.insert(std::make_pair(csid, newCS));
167 return csid;
168}
169
174{
175}
176
181 CallGraphNode* dst,
182 CallGraphEdge::CEDGEK kind, CallSiteID csId) const
183{
184 CallGraphEdge edge(src,dst,kind,csId);
185 return hasGraphEdge(&edge);
186}
187
189{
190 CallGraphEdge* outEdge = cgEdge->getSrcNode()->hasOutgoingEdge(cgEdge);
191 CallGraphEdge* inEdge = cgEdge->getDstNode()->hasIncomingEdge(cgEdge);
192 if (outEdge && inEdge)
193 {
194 assert(outEdge == inEdge && "edges not match");
195 return outEdge;
196 }
197 else
198 return nullptr;
199}
200
205 CallGraphNode* dst,
207{
208 for (CallGraphEdge::CallGraphEdgeSet::iterator iter = src->OutEdgeBegin();
209 iter != src->OutEdgeEnd(); ++iter)
210 {
211 CallGraphEdge* edge = (*iter);
212 if (edge->getEdgeKind() == kind && edge->getDstID() == dst->getId())
213 return edge;
214 }
215 return nullptr;
216}
217
218
240
245{
246 CallGraphNode* callGraphNode = getCallGraphNode(callee);
247 for(CallGraphNode::iterator it = callGraphNode->InEdgeBegin(), eit = callGraphNode->InEdgeEnd();
248 it!=eit; ++it)
249 {
250 for(CallGraphEdge::CallInstSet::const_iterator cit = (*it)->directCallsBegin(),
251 ecit = (*it)->directCallsEnd(); cit!=ecit; ++cit)
252 {
253 csSet.insert((*cit));
254 }
255 for(CallGraphEdge::CallInstSet::const_iterator cit = (*it)->indirectCallsBegin(),
256 ecit = (*it)->indirectCallsEnd(); cit!=ecit; ++cit)
257 {
258 csSet.insert((*cit));
259 }
260 }
261}
262
267{
268 CallGraphNode* callGraphNode = getCallGraphNode(callee);
269 for(CallGraphNode::iterator it = callGraphNode->InEdgeBegin(), eit = callGraphNode->InEdgeEnd();
270 it!=eit; ++it)
271 {
272 for(CallGraphEdge::CallInstSet::const_iterator cit = (*it)->directCallsBegin(),
273 ecit = (*it)->directCallsEnd(); cit!=ecit; ++cit)
274 {
275 csSet.insert((*cit));
276 }
277 }
278}
279
284{
285 CallGraphNode* callGraphNode = getCallGraphNode(callee);
286 for(CallGraphNode::iterator it = callGraphNode->InEdgeBegin(), eit = callGraphNode->InEdgeEnd();
287 it!=eit; ++it)
288 {
289 for(CallGraphEdge::CallInstSet::const_iterator cit = (*it)->indirectCallsBegin(),
290 ecit = (*it)->indirectCallsEnd(); cit!=ecit; ++cit)
291 {
292 csSet.insert((*cit));
293 }
294 }
295}
296
301{
303 return;
304
307 CallEdgeMap::const_iterator it = indirectCallMap.begin();
308 CallEdgeMap::const_iterator eit = indirectCallMap.end();
309 for (; it != eit; ++it)
310 {
311 const FunctionSet& targets = it->second;
312 if (targets.empty() == false)
313 {
314 const CallICFGNode* cs = it->first;
315 const FunObjVar* func = cs->getCaller();
317 isReachableFromProgEntry(reachableFromEntry, visitedNodes) == false)
318 writeWrnMsg(func->getName() + " has indirect call site but not reachable from main");
319 }
320 }
321}
322
327{
329
330 std::stack<const CallGraphNode*> nodeStack;
332 nodeStack.push(dstNode);
333 visitedNodes.set(dstNode->getId());
334
335 while (nodeStack.empty() == false)
336 {
337 CallGraphNode* node = const_cast<CallGraphNode*>(nodeStack.top());
338 nodeStack.pop();
339
340 if (node->getFunction() == srcFn)
341 return true;
342
343 for (CallGraphEdgeConstIter it = node->InEdgeBegin(), eit = node->InEdgeEnd(); it != eit; ++it)
344 {
346 if (visitedNodes.test_and_set(edge->getSrcID()))
347 nodeStack.push(edge->getSrcNode());
348 }
349 }
350
351 return false;
352}
353
357void CallGraph::dump(const std::string& filename)
358{
360}
361
363{
364 SVF::ViewGraph(this, "Call Graph");
365}
366
367
372{
374 CallGraphNode*callGraphNode = new CallGraphNode(id, fun);
375 addCallGraphNode(callGraphNode);
376}
377
379{
380 addGNode(cgNode->getId(), cgNode);
381 funToCallGraphNodeMap[cgNode->getFunction()] = cgNode;
383}
384
385const CallGraphNode* CallGraph::getCallGraphNode(const std::string& name) const
386{
387 for (const auto& item : *this)
388 {
389 if (item.second->getName() == name)
390 return item.second;
391 }
392 return nullptr;
393}
394
413
418
419namespace SVF
420{
421
425template<>
427{
428
431 DOTGraphTraits(bool isSimple = false) :
432 DefaultDOTGraphTraits(isSimple)
433 {
434 }
435
437 static std::string getGraphName(CallGraph*)
438 {
439 return "Call Graph";
440 }
442 static std::string getNodeLabel(CallGraphNode*node, CallGraph*)
443 {
444 return node->toString();
445 }
446
447 static std::string getNodeAttributes(CallGraphNode*node, CallGraph*)
448 {
449 const FunObjVar* fun = node->getFunction();
450 if (!SVFUtil::isExtCall(fun))
451 {
452 return "shape=box";
453 }
454 else
455 return "shape=Mrecord";
456 }
457
458 template<class EdgeIter>
460 CallGraph*)
461 {
462
463 //TODO: mark indirect call of Fork with different color
464 CallGraphEdge* edge = *(EI.getCurrent());
465 assert(edge && "No edge found!!");
466
467 std::string color;
468
469 if (edge->getEdgeKind() == CallGraphEdge::TDJoinEdge)
470 {
471 color = "color=green";
472 }
473 else if (edge->getEdgeKind() == CallGraphEdge::TDForkEdge)
474 {
475 color = "color=blue";
476 }
477 else
478 {
479 color = "color=black";
480 }
481 if (0 != edge->getIndirectCalls().size())
482 {
483 color = "color=red";
484 }
485 return color;
486 }
487
488 template<class EdgeIter>
490 {
491 CallGraphEdge* edge = *(EI.getCurrent());
492 assert(edge && "No edge found!!");
493
494 std::string str;
495 std::stringstream rawstr(str);
496 rawstr << edge->getCallSiteID();
497
498 return rawstr.str();
499 }
500};
501} // End namespace llvm
const char *const name
Definition cJSON.h:264
cJSON * item
Definition cJSON.h:222
NodeID getId() const
Get the memory object id.
void addInDirectCallSite(const CallICFGNode *call)
Definition CallGraph.cpp:60
void addDirectCallSite(const CallICFGNode *call)
Add direct and indirect callsite.
Definition CallGraph.cpp:54
CallInstSet indirectCalls
Definition CallGraph.h:64
virtual const std::string toString() const
Definition CallGraph.cpp:68
bool isDirectCallEdge() const
Definition CallGraph.h:87
Set< const CallICFGNode * > CallInstSet
Definition CallGraph.h:55
CallInstSet directCalls
Definition CallGraph.h:63
CallSiteID getCallSiteID() const
Get direct and indirect calls.
Definition CallGraph.h:83
const FunObjVar * getFunction() const
Get function of this call node.
Definition CallGraph.h:191
const std::string & getName() const
Definition CallGraph.cpp:46
virtual const std::string toString() const
Definition CallGraph.cpp:81
bool isReachableFromProgEntry(Map< NodeID, bool > &reachableFromEntry, NodeBS &visitedNodes) const
Return TRUE if this function can be reached from main.
Definition CallGraph.cpp:94
const FunObjVar * fun
Definition CallGraph.h:179
CallInstToCallGraphEdgesMap callinstToCallGraphEdgesMap
Map a call instruction to its corresponding call edges.
Definition CallGraph.h:268
void getAllCallSitesInvokingCallee(const FunObjVar *callee, CallGraphEdge::CallInstSet &csSet)
Get callsites invoking the callee.
void addIndirectCallGraphEdge(const CallICFGNode *cs, const FunObjVar *callerFun, const FunObjVar *calleeFun)
Add indirect call edges.
CallGraphEdge * hasGraphEdge(CallGraphEdge *cgEdge) const
Whether we have already created this call graph edge.
CallEdgeMap indirectCallMap
Indirect call map.
Definition CallGraph.h:259
void addCallGraphNode(CallGraphNode *cgNode)
add call graph node from database [only used this function when loading cgNodes from db results]
void addEdge(CallGraphEdge *edge)
Add call graph edge.
Definition CallGraph.h:296
const FunObjVar * getCallerOfCallSite(CallSiteID id) const
Definition CallGraph.cpp:89
void getIndCallSitesInvokingCallee(const FunObjVar *callee, CallGraphEdge::CallInstSet &csSet)
static IdToCallSiteMap idToCSMap
Map a callsite ID to a pair of call instruction and callee.
Definition CallGraph.h:263
static CallSiteID totalCallSiteNum
CallSiteIDs, start from 1;.
Definition CallGraph.h:264
Map< CallSiteID, CallSitePair > IdToCallSiteMap
Definition CallGraph.h:246
NodeID callGraphNodeNum
Definition CallGraph.h:270
const CallGraphNode * getCallGraphNode(const std::string &name) const
Get call graph node.
void destroy()
Clean up memory.
CallSiteID addCallSite(const CallICFGNode *cs, const FunObjVar *callee)
Add CallSiteID.
Definition CallGraph.h:279
FunToCallGraphNodeMap funToCallGraphNodeMap
Call Graph node map.
Definition CallGraph.h:267
CallGraphEdgeSet::const_iterator CallGraphEdgeConstIter
Definition CallGraph.h:250
CallGraph(CGEK k=NormCallGraph)
Constructor.
static CallSiteToIdMap csToIdMap
Call site information.
Definition CallGraph.h:262
const CallICFGNode * getCallSite(CallSiteID id) const
Definition CallGraph.h:408
bool isReachableBetweenFunctions(const FunObjVar *srcFn, const FunObjVar *dstFn) const
Whether its reachable between two functions.
void view()
View the graph from the debugger.
void dump(const std::string &filename)
Dump the graph.
void getDirCallSitesInvokingCallee(const FunObjVar *callee, CallGraphEdge::CallInstSet &csSet)
void verifyCallGraph()
Issue a warning if the function which has indirect call sites can not be reached from program entry.
u32_t numOfResolvedIndCallEdge
Definition CallGraph.h:271
CallGraphEdge * getGraphEdge(CallGraphNode *src, CallGraphNode *dst, CallGraphEdge::CEDGEK kind, CallSiteID csId)
Get call graph edge via nodes.
Map< CallSitePair, CallSiteID > CallSiteToIdMap
Definition CallGraph.h:245
void addDirectCallGraphEdge(CallGraphEdge *cgEdge)
add direct call graph edge from database [only used this function when loading cgEdges from db result...
Set< const FunObjVar * > FunctionSet
Definition CallGraph.h:247
const FunObjVar * getCalledFunction() const
Definition ICFGNode.h:500
const FunObjVar * getCaller() const
Return callsite.
Definition ICFGNode.h:452
NodeType * getSrcNode() const
NodeType * getDstNode() const
NodeID getDstID() const
NodeID getSrcID() const
get methods of the components
void addGNode(NodeID id, NodeType *node)
Add a Node.
iterator OutEdgeEnd()
GEdgeSetTy::iterator iterator
iterator OutEdgeBegin()
iterators
GEdgeSetTy::const_iterator const_iterator
iterator InEdgeBegin()
iterator InEdgeEnd()
static void WriteGraphToFile(SVF::OutStream &O, const std::string &GraphName, const GraphType &GT, bool simple=false)
static const Option< bool > DisableWarn
Definition Options.h:202
NodeID getId() const
Get ID.
Definition SVFValue.h:160
NodeID id
Node ID.
Definition SVFValue.h:206
virtual const std::string & getName() const
Definition SVFValue.h:186
void set(unsigned Idx)
iterator begin() const
bool isProgEntryFunction(const FunObjVar *)
Program entry function e.g. main.
Definition SVFUtil.cpp:442
bool isExtCall(const FunObjVar *fun)
Definition SVFUtil.cpp:437
void writeWrnMsg(const std::string &msg)
Writes a message run through wrnMsg.
Definition SVFUtil.cpp:68
const ValVar * getForkedFun(const CallICFGNode *inst)
Return thread fork function.
Definition SVFUtil.h:331
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:52
for isBitcode
Definition BasicTypes.h:68
unsigned CallSiteID
Definition GeneralType.h:58
u32_t NodeID
Definition GeneralType.h:56
void ViewGraph(const GraphType &G, const std::string &name, bool ShortNames=false, GraphProgram::Name Program=GraphProgram::DOT)
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74
DOTGraphTraits(bool isSimple=false)
static std::string getNodeAttributes(CallGraphNode *node, CallGraph *)
static std::string getGraphName(CallGraph *)
Return name of the graph.
static std::string getNodeLabel(CallGraphNode *node, CallGraph *)
Return function name;.
static std::string getEdgeSourceLabel(NodeType *, EdgeIter EI)
static std::string getEdgeAttributes(CallGraphNode *, EdgeIter EI, CallGraph *)
NodeType::iterator ChildIteratorType