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