Static Value-Flow Analysis
Loading...
Searching...
No Matches
PTACallGraph.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/PTACallGraph.h"
32#include "Graphs/PTACallGraph.h"
33#include "SVFIR/SVFIR.h"
34#include "SVFIR/SVFModule.h"
35#include "Util/SVFUtil.h"
36#include <sstream>
37
38using namespace SVF;
39using namespace SVFUtil;
40
44
46
48{
49 assert(call->getCalledFunction() && "not a direct callsite??");
50 directCalls.insert(call);
51}
52
54{
55 assert((nullptr == call->getCalledFunction() || !SVFUtil::isa<FunValVar>(SVFUtil::getForkedFun(call))) &&
56 "not an indirect callsite??");
57 indirectCalls.insert(call);
58}
60
61const std::string PTACallGraphEdge::toString() const
62{
63 std::string str;
64 std::stringstream rawstr(str);
65 rawstr << "CallSite ID: " << getCallSiteID();
67 rawstr << "direct call";
68 else
69 rawstr << "indirect call";
70 rawstr << "[" << getDstID() << "<--" << getSrcID() << "]\t";
71 return rawstr.str();
72}
73
74const std::string PTACallGraphNode::toString() const
75{
76 std::string str;
77 std::stringstream rawstr(str);
78 rawstr << "PTACallGraphNode ID: " << getId() << " {fun: " << fun->getName() << "}";
79 return rawstr.str();
80}
81
83{
84 std::stack<const PTACallGraphNode*> nodeStack;
86 nodeStack.push(this);
88
89 while (nodeStack.empty() == false)
90 {
91 PTACallGraphNode* node = const_cast<PTACallGraphNode*>(nodeStack.top());
92 nodeStack.pop();
93
95 return true;
96
97 for (const_iterator it = node->InEdgeBegin(), eit = node->InEdgeEnd(); it != eit; ++it)
98 {
100 if (visitedNodes.test_and_set(edge->getSrcID()))
101 nodeStack.push(edge->getSrcNode());
102 }
103 }
104
105 return false;
106}
107
108
115
118{
119 callGraphNodeNum = other.getTotalNodeNum();
122
124 for (const auto& item : other)
125 {
126 const PTACallGraphNode* cgn = item.second;
127 PTACallGraphNode* callGraphNode = new PTACallGraphNode(cgn->getId(), cgn->getFunction());
128 addGNode(cgn->getId(),callGraphNode);
129 funToCallGraphNodeMap[cgn->getFunction()] = callGraphNode;
130 }
131
133 for (const auto& item : other.callinstToCallGraphEdgesMap)
134 {
135 const CallICFGNode* cs = item.first;
136 for (const PTACallGraphEdge* edge : item.second)
137 {
138 PTACallGraphNode* src = getCallGraphNode(edge->getSrcID());
139 PTACallGraphNode* dst = getCallGraphNode(edge->getDstID());
140 CallSiteID csId = addCallSite(cs, dst->getFunction());
141
143 newEdge->addDirectCallSite(cs);
146 }
147 }
148
149}
150
155{
156}
157
162 PTACallGraphNode* dst,
163 PTACallGraphEdge::CEDGEK kind, CallSiteID csId) const
164{
165 PTACallGraphEdge edge(src,dst,kind,csId);
168 if (outEdge && inEdge)
169 {
170 assert(outEdge == inEdge && "edges not match");
171 return outEdge;
172 }
173 else
174 return nullptr;
175}
176
181 PTACallGraphNode* dst,
183{
184 for (PTACallGraphEdge::CallGraphEdgeSet::iterator iter = src->OutEdgeBegin();
185 iter != src->OutEdgeEnd(); ++iter)
186 {
187 PTACallGraphEdge* edge = (*iter);
188 if (edge->getEdgeKind() == kind && edge->getDstID() == dst->getId())
189 return edge;
190 }
191 return nullptr;
192}
193
194
216
221{
222 PTACallGraphNode* callGraphNode = getCallGraphNode(callee);
223 for(PTACallGraphNode::iterator it = callGraphNode->InEdgeBegin(), eit = callGraphNode->InEdgeEnd();
224 it!=eit; ++it)
225 {
226 for(PTACallGraphEdge::CallInstSet::const_iterator cit = (*it)->directCallsBegin(),
227 ecit = (*it)->directCallsEnd(); cit!=ecit; ++cit)
228 {
229 csSet.insert((*cit));
230 }
231 for(PTACallGraphEdge::CallInstSet::const_iterator cit = (*it)->indirectCallsBegin(),
232 ecit = (*it)->indirectCallsEnd(); cit!=ecit; ++cit)
233 {
234 csSet.insert((*cit));
235 }
236 }
237}
238
243{
244 PTACallGraphNode* callGraphNode = getCallGraphNode(callee);
245 for(PTACallGraphNode::iterator it = callGraphNode->InEdgeBegin(), eit = callGraphNode->InEdgeEnd();
246 it!=eit; ++it)
247 {
248 for(PTACallGraphEdge::CallInstSet::const_iterator cit = (*it)->directCallsBegin(),
249 ecit = (*it)->directCallsEnd(); cit!=ecit; ++cit)
250 {
251 csSet.insert((*cit));
252 }
253 }
254}
255
260{
261 PTACallGraphNode* callGraphNode = getCallGraphNode(callee);
262 for(PTACallGraphNode::iterator it = callGraphNode->InEdgeBegin(), eit = callGraphNode->InEdgeEnd();
263 it!=eit; ++it)
264 {
265 for(PTACallGraphEdge::CallInstSet::const_iterator cit = (*it)->indirectCallsBegin(),
266 ecit = (*it)->indirectCallsEnd(); cit!=ecit; ++cit)
267 {
268 csSet.insert((*cit));
269 }
270 }
271}
272
277{
278 CallEdgeMap::const_iterator it = indirectCallMap.begin();
279 CallEdgeMap::const_iterator eit = indirectCallMap.end();
280 for (; it != eit; ++it)
281 {
282 const FunctionSet& targets = it->second;
283 if (targets.empty() == false)
284 {
285 const CallICFGNode* cs = it->first;
286 const SVFFunction* func = cs->getCaller();
287 if (getCallGraphNode(func)->isReachableFromProgEntry() == false)
288 writeWrnMsg(func->getName() + " has indirect call site but not reachable from main");
289 }
290 }
291}
292
297{
299
300 std::stack<const PTACallGraphNode*> nodeStack;
302 nodeStack.push(dstNode);
303 visitedNodes.set(dstNode->getId());
304
305 while (nodeStack.empty() == false)
306 {
307 PTACallGraphNode* node = const_cast<PTACallGraphNode*>(nodeStack.top());
308 nodeStack.pop();
309
310 if (node->getFunction() == srcFn)
311 return true;
312
313 for (CallGraphEdgeConstIter it = node->InEdgeBegin(), eit = node->InEdgeEnd(); it != eit; ++it)
314 {
316 if (visitedNodes.test_and_set(edge->getSrcID()))
317 nodeStack.push(edge->getSrcNode());
318 }
319 }
320
321 return false;
322}
323
327void PTACallGraph::dump(const std::string& filename)
328{
330}
331
333{
334 SVF::ViewGraph(this, "Call Graph");
335}
336
337
342{
344 PTACallGraphNode*callGraphNode = new PTACallGraphNode(id, fun);
345 addGNode(id, callGraphNode);
346 funToCallGraphNodeMap[callGraphNode->getFunction()] = callGraphNode;
348}
349
351{
352 for (const auto& item : *this)
353 {
354 if (item.second->getName() == name)
355 return item.second;
356 }
357 return nullptr;
358}
359
378
379namespace SVF
380{
381
385template<>
387{
388
391 DOTGraphTraits(bool isSimple = false) :
392 DefaultDOTGraphTraits(isSimple)
393 {
394 }
395
397 static std::string getGraphName(PTACallGraph*)
398 {
399 return "Call Graph";
400 }
402 static std::string getNodeLabel(PTACallGraphNode*node, PTACallGraph*)
403 {
404 return node->toString();
405 }
406
408 {
409 const SVFFunction* fun = node->getFunction();
410 if (!SVFUtil::isExtCall(fun))
411 {
412 return "shape=box";
413 }
414 else
415 return "shape=Mrecord";
416 }
417
418 template<class EdgeIter>
421 {
422
423 //TODO: mark indirect call of Fork with different color
424 PTACallGraphEdge* edge = *(EI.getCurrent());
425 assert(edge && "No edge found!!");
426
427 std::string color;
428
429 if (edge->getEdgeKind() == PTACallGraphEdge::TDJoinEdge)
430 {
431 color = "color=green";
432 }
433 else if (edge->getEdgeKind() == PTACallGraphEdge::TDForkEdge)
434 {
435 color = "color=blue";
436 }
437 else
438 {
439 color = "color=black";
440 }
441 if (0 != edge->getIndirectCalls().size())
442 {
443 color = "color=red";
444 }
445 return color;
446 }
447
448 template<class EdgeIter>
450 {
451 PTACallGraphEdge* edge = *(EI.getCurrent());
452 assert(edge && "No edge found!!");
453
454 std::string str;
455 std::stringstream rawstr(str);
456 rawstr << edge->getCallSiteID();
457
458 return rawstr.str();
459 }
460};
461} // End namespace llvm
const char *const name
Definition cJSON.h:264
cJSON * item
Definition cJSON.h:222
const SVFFunction * getCalledFunction() const
Definition ICFGNode.h:518
const SVFFunction * getCaller() const
Return callsite.
Definition ICFGNode.h:470
NodeID getDstID() const
NodeID getSrcID() const
get methods of the components
void addGNode(NodeID id, NodeType *node)
Add a Node.
bool hasIncomingEdge() const
Has incoming/outgoing edge set.
bool hasOutgoingEdge() const
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)
virtual const std::string toString() const
CallInstSet directCalls
CallInstSet indirectCalls
bool isDirectCallEdge() const
void addDirectCallSite(const CallICFGNode *call)
Add direct and indirect callsite.
void addInDirectCallSite(const CallICFGNode *call)
Set< const CallICFGNode * > CallInstSet
CallSiteID getCallSiteID() const
Get direct and indirect calls.
const SVFFunction * getFunction() const
Get function of this call node.
const SVFFunction * fun
virtual const std::string toString() const
bool isReachableFromProgEntry() const
Return TRUE if this function can be reached from main.
void getDirCallSitesInvokingCallee(const SVFFunction *callee, PTACallGraphEdge::CallInstSet &csSet)
PTACallGraphEdge * getGraphEdge(PTACallGraphNode *src, PTACallGraphNode *dst, PTACallGraphEdge::CEDGEK kind, CallSiteID csId)
Get call graph edge via nodes.
static CallSiteID totalCallSiteNum
CallSiteIDs, start from 1;.
void addEdge(PTACallGraphEdge *edge)
Add call graph edge.
void addIndirectCallGraphEdge(const CallICFGNode *cs, const SVFFunction *callerFun, const SVFFunction *calleeFun)
Add indirect call edges.
static IdToCallSiteMap idToCSMap
Map a callsite ID to a pair of call instruction and callee.
Set< const SVFFunction * > FunctionSet
Map< CallSiteID, CallSitePair > IdToCallSiteMap
PTACallGraph(CGEK k=NormCallGraph)
Constructor.
void addDirectCallGraphEdge(const CallICFGNode *call, const SVFFunction *callerFun, const SVFFunction *calleeFun)
Add direct 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.
static CallSiteToIdMap csToIdMap
Call site information.
void view()
View the graph from the debugger.
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)
CallSiteID addCallSite(const CallICFGNode *cs, const SVFFunction *callee)
Add CallSiteID.
FunToCallGraphNodeMap funToCallGraphNodeMap
Call Graph node map.
void getIndCallSitesInvokingCallee(const SVFFunction *callee, PTACallGraphEdge::CallInstSet &csSet)
CallGraphEdgeSet::const_iterator CallGraphEdgeConstIter
bool isReachableBetweenFunctions(const SVFFunction *srcFn, const SVFFunction *dstFn) const
Whether its reachable between two functions.
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.
CallEdgeMap indirectCallMap
Indirect call map.
u32_t numOfResolvedIndCallEdge
Map< CallSitePair, CallSiteID > CallSiteToIdMap
const PTACallGraphNode * getCallGraphNode(const std::string &name)
Get call graph node.
NodeID getId() const
Get ID.
const std::string & getName() const
Definition SVFValue.h:244
void set(unsigned Idx)
bool isExtCall(const SVFFunction *fun)
Definition SVFUtil.h:269
bool isProgEntryFunction(const SVFFunction *fun)
Program entry function e.g. main.
Definition SVFUtil.h:316
void writeWrnMsg(const std::string &msg)
Writes a message run through wrnMsg.
Definition SVFUtil.cpp:67
const ValVar * getForkedFun(const CallICFGNode *inst)
Return thread fork function.
Definition SVFUtil.h:343
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:50
for isBitcode
Definition BasicTypes.h:68
unsigned CallSiteID
Definition GeneralType.h:57
u32_t NodeID
Definition GeneralType.h:55
void ViewGraph(const GraphType &G, const std::string &name, bool ShortNames=false, GraphProgram::Name Program=GraphProgram::DOT)
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74
static std::string getEdgeSourceLabel(NodeType *, EdgeIter EI)
static std::string getEdgeAttributes(PTACallGraphNode *, EdgeIter EI, PTACallGraph *)
static std::string getGraphName(PTACallGraph *)
Return name of the graph.
static std::string getNodeLabel(PTACallGraphNode *node, PTACallGraph *)
Return function name;.
static std::string getNodeAttributes(PTACallGraphNode *node, PTACallGraph *)