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 <functional>
32#include <sstream>
33
34#include "Graphs/CallGraph.h"
35#include "Graphs/GraphPrinter.h"
36#include "Util/Options.h"
37#include "Util/SVFUtil.h"
38
39using namespace SVF;
40using namespace SVFUtil;
41
45
46
47const std::string &CallGraphNode::getName() const
48{
49 return fun->getName();
50}
51
52
54
56{
57 assert(call->getCalledFunction() && "not a direct callsite??");
58 directCalls.insert(call);
59}
60
62{
63 assert((nullptr == call->getCalledFunction() || !SVFUtil::isa<FunValVar>(SVFUtil::getForkedFun(call))) &&
64 "not an indirect callsite??");
65 indirectCalls.insert(call);
66}
68
69const std::string CallGraphEdge::toString() const
70{
71 std::string str;
72 std::stringstream rawstr(str);
73 rawstr << "CallSite ID: " << getCallSiteID();
75 rawstr << "direct call";
76 else
77 rawstr << "indirect call";
78 rawstr << "[" << getDstID() << "<--" << getSrcID() << "]\t";
79 return rawstr.str();
80}
81
82const std::string CallGraphNode::toString() const
83{
84 std::string str;
85 std::stringstream rawstr(str);
86 rawstr << "CallGraphNode ID: " << getId() << " {fun: " << fun->getName() << "}";
87 return rawstr.str();
88}
89
91{
92 return getCallSite(id)->getCaller();
93}
94
96{
97 std::function<bool(const CallGraphNode*)> dfs =
99 {
100 NodeID id = v->getId();
101 if (!visitedNodes.test_and_set(id))
102 return reachableFromEntry[id];
103
104 if (SVFUtil::isProgEntryFunction(v->getFunction()))
105 return reachableFromEntry[id] = true;
106
107 bool result = false;
108 for (const_iterator it = v->InEdgeBegin(), eit = v->InEdgeEnd(); it != eit; ++it)
109 {
110 CallGraphEdge* edge = *it;
111 result |= dfs(edge->getSrcNode());
112 if (result)
113 break;
114 }
115 return reachableFromEntry[id] = result;
116 };
117
118 return dfs(this);
119}
120
121
128
131{
135
137 for (const auto& item : other)
138 {
139 const CallGraphNode* cgn = item.second;
140 CallGraphNode* callGraphNode = new CallGraphNode(cgn->getId(), cgn->getFunction());
141 addGNode(cgn->getId(),callGraphNode);
142 funToCallGraphNodeMap[cgn->getFunction()] = callGraphNode;
143 }
144
146 for (const auto& item : other.callinstToCallGraphEdgesMap)
147 {
148 const CallICFGNode* cs = item.first;
149 for (const CallGraphEdge* edge : item.second)
150 {
151 CallGraphNode* src = getCallGraphNode(edge->getSrcID());
152 CallGraphNode* dst = getCallGraphNode(edge->getDstID());
153 CallSiteID csId = addCallSite(cs, dst->getFunction());
154
156 newEdge->addDirectCallSite(cs);
159 }
160 }
161
162}
163
164CallSiteID CallGraph::addCallSite(const CallICFGNode* cs, const FunObjVar* callee, const CallSiteID csid, std::pair<const CallICFGNode*, const FunObjVar*> newCS)
165{
166 csToIdMap.insert(std::make_pair(newCS, csid));
167 idToCSMap.insert(std::make_pair(csid, newCS));
168 return csid;
169}
170
175{
176}
177
182 CallGraphNode* dst,
183 CallGraphEdge::CEDGEK kind, CallSiteID csId) const
184{
185 CallGraphEdge edge(src,dst,kind,csId);
186 return hasGraphEdge(&edge);
187}
188
190{
191 CallGraphEdge* outEdge = cgEdge->getSrcNode()->hasOutgoingEdge(cgEdge);
192 CallGraphEdge* inEdge = cgEdge->getDstNode()->hasIncomingEdge(cgEdge);
193 if (outEdge && inEdge)
194 {
195 assert(outEdge == inEdge && "edges not match");
196 return outEdge;
197 }
198 else
199 return nullptr;
200}
201
206 CallGraphNode* dst,
208{
209 for (CallGraphEdge::CallGraphEdgeSet::iterator iter = src->OutEdgeBegin();
210 iter != src->OutEdgeEnd(); ++iter)
211 {
212 CallGraphEdge* edge = (*iter);
213 if (edge->getEdgeKind() == kind && edge->getDstID() == dst->getId())
214 return edge;
215 }
216 return nullptr;
217}
218
219
241
246{
247 CallGraphNode* callGraphNode = getCallGraphNode(callee);
248 for(CallGraphNode::iterator it = callGraphNode->InEdgeBegin(), eit = callGraphNode->InEdgeEnd();
249 it!=eit; ++it)
250 {
251 for(CallGraphEdge::CallInstSet::const_iterator cit = (*it)->directCallsBegin(),
252 ecit = (*it)->directCallsEnd(); cit!=ecit; ++cit)
253 {
254 csSet.insert((*cit));
255 }
256 for(CallGraphEdge::CallInstSet::const_iterator cit = (*it)->indirectCallsBegin(),
257 ecit = (*it)->indirectCallsEnd(); cit!=ecit; ++cit)
258 {
259 csSet.insert((*cit));
260 }
261 }
262}
263
268{
269 CallGraphNode* callGraphNode = getCallGraphNode(callee);
270 for(CallGraphNode::iterator it = callGraphNode->InEdgeBegin(), eit = callGraphNode->InEdgeEnd();
271 it!=eit; ++it)
272 {
273 for(CallGraphEdge::CallInstSet::const_iterator cit = (*it)->directCallsBegin(),
274 ecit = (*it)->directCallsEnd(); cit!=ecit; ++cit)
275 {
276 csSet.insert((*cit));
277 }
278 }
279}
280
285{
286 CallGraphNode* callGraphNode = getCallGraphNode(callee);
287 for(CallGraphNode::iterator it = callGraphNode->InEdgeBegin(), eit = callGraphNode->InEdgeEnd();
288 it!=eit; ++it)
289 {
290 for(CallGraphEdge::CallInstSet::const_iterator cit = (*it)->indirectCallsBegin(),
291 ecit = (*it)->indirectCallsEnd(); cit!=ecit; ++cit)
292 {
293 csSet.insert((*cit));
294 }
295 }
296}
297
302{
304 return;
305
308 CallEdgeMap::const_iterator it = indirectCallMap.begin();
309 CallEdgeMap::const_iterator eit = indirectCallMap.end();
310 for (; it != eit; ++it)
311 {
312 const FunctionSet& targets = it->second;
313 if (targets.empty() == false)
314 {
315 const CallICFGNode* cs = it->first;
316 const FunObjVar* func = cs->getCaller();
318 isReachableFromProgEntry(reachableFromEntry, visitedNodes) == false)
319 writeWrnMsg(func->getName() + " has indirect call site but not reachable from main");
320 }
321 }
322}
323
328{
330
331 std::stack<const CallGraphNode*> nodeStack;
333 nodeStack.push(dstNode);
334 visitedNodes.set(dstNode->getId());
335
336 while (nodeStack.empty() == false)
337 {
338 CallGraphNode* node = const_cast<CallGraphNode*>(nodeStack.top());
339 nodeStack.pop();
340
341 if (node->getFunction() == srcFn)
342 return true;
343
344 for (CallGraphEdgeConstIter it = node->InEdgeBegin(), eit = node->InEdgeEnd(); it != eit; ++it)
345 {
346 CallGraphEdge* edge = *it;
347 if (visitedNodes.test_and_set(edge->getSrcID()))
348 nodeStack.push(edge->getSrcNode());
349 }
350 }
351
352 return false;
353}
354
358void CallGraph::dump(const std::string& filename)
359{
361}
362
364{
365 SVF::ViewGraph(this, "Call Graph");
366}
367
368
373{
375 CallGraphNode*callGraphNode = new CallGraphNode(id, fun);
376 addCallGraphNode(callGraphNode);
377}
378
380{
381 addGNode(cgNode->getId(), cgNode);
382 funToCallGraphNodeMap[cgNode->getFunction()] = cgNode;
384}
385
386const CallGraphNode* CallGraph::getCallGraphNode(const std::string& name) const
387{
388 for (const auto& item : *this)
389 {
390 if (item.second->getName() == name)
391 return item.second;
392 }
393 return nullptr;
394}
395
414
419
420namespace SVF
421{
422
426template<>
428{
429
432 DOTGraphTraits(bool isSimple = false) :
433 DefaultDOTGraphTraits(isSimple)
434 {
435 }
436
438 static std::string getGraphName(CallGraph*)
439 {
440 return "Call Graph";
441 }
443 static std::string getNodeLabel(CallGraphNode*node, CallGraph*)
444 {
445 return node->toString();
446 }
447
448 static std::string getNodeAttributes(CallGraphNode*node, CallGraph*)
449 {
450 const FunObjVar* fun = node->getFunction();
451 if (!SVFUtil::isExtCall(fun))
452 {
453 return "shape=record";
454 }
455 else
456 return "shape=Mrecord";
457 }
458
459 template<class EdgeIter>
461 CallGraph*)
462 {
463
464 //TODO: mark indirect call of Fork with different color
465 CallGraphEdge* edge = *(EI.getCurrent());
466 assert(edge && "No edge found!!");
467
468 std::string color;
469
470 if (edge->getEdgeKind() == CallGraphEdge::TDJoinEdge)
471 {
472 color = "color=green";
473 }
474 else if (edge->getEdgeKind() == CallGraphEdge::TDForkEdge)
475 {
476 color = "color=blue";
477 }
478 else
479 {
480 color = "color=black";
481 }
482 if (0 != edge->getIndirectCalls().size())
483 {
484 color = "color=red";
485 }
486 return color;
487 }
488
489 template<class EdgeIter>
491 {
492 CallGraphEdge* edge = *(EI.getCurrent());
493 assert(edge && "No edge found!!");
494
495 std::string str;
496 std::stringstream rawstr(str);
497 rawstr << edge->getCallSiteID();
498
499 return rawstr.str();
500 }
501};
502} // 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:61
void addDirectCallSite(const CallICFGNode *call)
Add direct and indirect callsite.
Definition CallGraph.cpp:55
CallInstSet indirectCalls
Definition CallGraph.h:64
virtual const std::string toString() const
Definition CallGraph.cpp:69
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:47
virtual const std::string toString() const
Definition CallGraph.cpp:82
bool isReachableFromProgEntry(Map< NodeID, bool > &reachableFromEntry, NodeBS &visitedNodes) const
Return TRUE if this function can be reached from main.
Definition CallGraph.cpp:95
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:90
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:501
const FunObjVar * getCaller() const
Return callsite.
Definition ICFGNode.h:453
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.
u32_t getTotalNodeNum() const
Get total number of node/edge.
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:195
NodeID getId() const
Get ID.
Definition SVFValue.h:158
NodeID id
Node ID.
Definition SVFValue.h:204
virtual const std::string & getName() const
Definition SVFValue.h:184
void set(unsigned Idx)
iterator begin() const
bool isProgEntryFunction(const FunObjVar *)
Program entry function e.g. main.
Definition SVFUtil.cpp:446
bool isExtCall(const FunObjVar *fun)
Definition SVFUtil.cpp:441
void writeWrnMsg(const std::string &msg)
Writes a message run through wrnMsg.
Definition SVFUtil.cpp:72
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:70
unsigned CallSiteID
Definition GeneralType.h:78
u32_t NodeID
Definition GeneralType.h:76
void ViewGraph(const GraphType &G, const std::string &name, bool ShortNames=false, GraphProgram::Name Program=GraphProgram::DOT)
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76
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