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/CallGraph.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 CallGraphNode* 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 CallGraphEdge* 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
337namespace SVF
338{
339
343template<>
345{
346
349 DOTGraphTraits(bool isSimple = false) :
350 DefaultDOTGraphTraits(isSimple)
351 {
352 }
353
355 static std::string getGraphName(PTACallGraph*)
356 {
357 return "Call Graph";
358 }
360 static std::string getNodeLabel(PTACallGraphNode*node, PTACallGraph*)
361 {
362 return node->toString();
363 }
364
366 {
367 const SVFFunction* fun = node->getFunction();
368 if (!SVFUtil::isExtCall(fun))
369 {
370 return "shape=box";
371 }
372 else
373 return "shape=Mrecord";
374 }
375
376 template<class EdgeIter>
379 {
380
381 //TODO: mark indirect call of Fork with different color
382 PTACallGraphEdge* edge = *(EI.getCurrent());
383 assert(edge && "No edge found!!");
384
385 std::string color;
386
387 if (edge->getEdgeKind() == PTACallGraphEdge::TDJoinEdge)
388 {
389 color = "color=green";
390 }
391 else if (edge->getEdgeKind() == PTACallGraphEdge::TDForkEdge)
392 {
393 color = "color=blue";
394 }
395 else
396 {
397 color = "color=black";
398 }
399 if (0 != edge->getIndirectCalls().size())
400 {
401 color = "color=red";
402 }
403 return color;
404 }
405
406 template<class EdgeIter>
408 {
409 PTACallGraphEdge* edge = *(EI.getCurrent());
410 assert(edge && "No edge found!!");
411
412 std::string str;
413 std::stringstream rawstr(str);
414 rawstr << edge->getCallSiteID();
415
416 return rawstr.str();
417 }
418};
419} // End namespace llvm
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 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.
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
PTACallGraphNode * getCallGraphNode(NodeID id) const
Get call graph node.
NodeID getId() const
Get ID.
const std::string & getName() const
Definition SVFValue.h:243
void set(unsigned Idx)
bool isExtCall(const SVFFunction *fun)
Definition SVFUtil.h:278
bool isProgEntryFunction(const SVFFunction *fun)
Program entry function e.g. main.
Definition SVFUtil.h:325
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:358
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:50
for isBitcode
Definition BasicTypes.h:68
unsigned CallSiteID
Definition GeneralType.h:58
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 *)