Static Value-Flow Analysis
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 "SVFIR/SVFIR.h"
33 #include "SVFIR/SVFModule.h"
34 #include "Util/SVFUtil.h"
35 #include <sstream>
36 
37 using namespace SVF;
38 using namespace SVFUtil;
39 
43 
44 
46 
48 {
49  assert(call->getCalledFunction() && "not a direct callsite??");
50  directCalls.insert(call);
51 }
52 
54 {
55  assert((nullptr == call->getCalledFunction() || nullptr == SVFUtil::dyn_cast<SVFFunction> (SVFUtil::getForkedFun(call)->getValue())) && "not an indirect callsite??");
56  indirectCalls.insert(call);
57 }
59 
61 {
62  std::string str;
63  std::stringstream rawstr(str);
64  rawstr << "CallSite ID: " << getCallSiteID();
65  if(isDirectCallEdge())
66  rawstr << "direct call";
67  else
68  rawstr << "indirect call";
69  rawstr << "[" << getDstID() << "<--" << getSrcID() << "]\t";
70  return rawstr.str();
71 }
72 
74 {
75  std::string str;
76  std::stringstream rawstr(str);
77  rawstr << "PTACallGraphNode ID: " << getId() << " {fun: " << fun->getName() << "}";
78  return rawstr.str();
79 }
80 
82 {
83  std::stack<const PTACallGraphNode*> nodeStack;
84  NodeBS visitedNodes;
85  nodeStack.push(this);
86  visitedNodes.set(getId());
87 
88  while (nodeStack.empty() == false)
89  {
90  PTACallGraphNode* node = const_cast<PTACallGraphNode*>(nodeStack.top());
91  nodeStack.pop();
92 
94  return true;
95 
96  for (const_iterator it = node->InEdgeBegin(), eit = node->InEdgeEnd(); it != eit; ++it)
97  {
98  PTACallGraphEdge* edge = *it;
99  if (visitedNodes.test_and_set(edge->getSrcID()))
100  nodeStack.push(edge->getSrcNode());
101  }
102  }
103 
104  return false;
105 }
106 
107 
110 {
111  callGraphNodeNum = 0;
113 }
114 
117 {
120  kind = other.kind;
121 
123  for (const auto& item : other)
124  {
125  const PTACallGraphNode* cgn = item.second;
126  PTACallGraphNode* callGraphNode = new PTACallGraphNode(cgn->getId(), cgn->getFunction());
127  addGNode(cgn->getId(),callGraphNode);
128  funToCallGraphNodeMap[cgn->getFunction()] = callGraphNode;
129  }
130 
132  for (const auto& item : other.callinstToCallGraphEdgesMap)
133  {
134  const CallICFGNode* cs = item.first;
135  for (const PTACallGraphEdge* edge : item.second)
136  {
140  newEdge->addDirectCallSite(cs);
141  addEdge(newEdge);
142  callinstToCallGraphEdgesMap[cs].insert(newEdge);
143  }
144  }
145 
146 }
147 
152 {
153 }
154 
159 {
161  PTACallGraphNode*callGraphNode = new PTACallGraphNode(id, fun);
162  addGNode(id, callGraphNode);
163  funToCallGraphNodeMap[callGraphNode->getFunction()] = callGraphNode;
165 }
166 
171  PTACallGraphNode* dst,
172  PTACallGraphEdge::CEDGEK kind, CallSiteID csId) const
173 {
174  PTACallGraphEdge edge(src,dst,kind,csId);
175  PTACallGraphEdge* outEdge = src->hasOutgoingEdge(&edge);
176  PTACallGraphEdge* inEdge = dst->hasIncomingEdge(&edge);
177  if (outEdge && inEdge)
178  {
179  assert(outEdge == inEdge && "edges not match");
180  return outEdge;
181  }
182  else
183  return nullptr;
184 }
185 
190  PTACallGraphNode* dst,
192 {
193  for (PTACallGraphEdge::CallGraphEdgeSet::iterator iter = src->OutEdgeBegin();
194  iter != src->OutEdgeEnd(); ++iter)
195  {
196  PTACallGraphEdge* edge = (*iter);
197  if (edge->getEdgeKind() == kind && edge->getDstID() == dst->getId())
198  return edge;
199  }
200  return nullptr;
201 }
202 
206 void PTACallGraph::addDirectCallGraphEdge(const CallICFGNode* cs,const SVFFunction* callerFun, const SVFFunction* calleeFun)
207 {
208 
209  PTACallGraphNode* caller = getCallGraphNode(callerFun);
210  PTACallGraphNode* callee = getCallGraphNode(calleeFun);
211 
212  CallSiteID csId = addCallSite(cs, callee->getFunction());
213 
214  if(!hasGraphEdge(caller,callee, PTACallGraphEdge::CallRetEdge,csId))
215  {
216  PTACallGraphEdge* edge = new PTACallGraphEdge(caller,callee, PTACallGraphEdge::CallRetEdge,csId);
217  edge->addDirectCallSite(cs);
218  addEdge(edge);
219  callinstToCallGraphEdgesMap[cs].insert(edge);
220  }
221 }
222 
226 void PTACallGraph::addIndirectCallGraphEdge(const CallICFGNode* cs,const SVFFunction* callerFun, const SVFFunction* calleeFun)
227 {
228 
229  PTACallGraphNode* caller = getCallGraphNode(callerFun);
230  PTACallGraphNode* callee = getCallGraphNode(calleeFun);
231 
233 
234  CallSiteID csId = addCallSite(cs, callee->getFunction());
235 
236  if(!hasGraphEdge(caller,callee, PTACallGraphEdge::CallRetEdge,csId))
237  {
238  PTACallGraphEdge* edge = new PTACallGraphEdge(caller,callee, PTACallGraphEdge::CallRetEdge, csId);
239  edge->addInDirectCallSite(cs);
240  addEdge(edge);
241  callinstToCallGraphEdgesMap[cs].insert(edge);
242  }
243 }
244 
249 {
250  PTACallGraphNode* callGraphNode = getCallGraphNode(callee);
251  for(PTACallGraphNode::iterator it = callGraphNode->InEdgeBegin(), eit = callGraphNode->InEdgeEnd();
252  it!=eit; ++it)
253  {
254  for(PTACallGraphEdge::CallInstSet::const_iterator cit = (*it)->directCallsBegin(),
255  ecit = (*it)->directCallsEnd(); cit!=ecit; ++cit)
256  {
257  csSet.insert((*cit));
258  }
259  for(PTACallGraphEdge::CallInstSet::const_iterator cit = (*it)->indirectCallsBegin(),
260  ecit = (*it)->indirectCallsEnd(); cit!=ecit; ++cit)
261  {
262  csSet.insert((*cit));
263  }
264  }
265 }
266 
271 {
272  PTACallGraphNode* callGraphNode = getCallGraphNode(callee);
273  for(PTACallGraphNode::iterator it = callGraphNode->InEdgeBegin(), eit = callGraphNode->InEdgeEnd();
274  it!=eit; ++it)
275  {
276  for(PTACallGraphEdge::CallInstSet::const_iterator cit = (*it)->directCallsBegin(),
277  ecit = (*it)->directCallsEnd(); cit!=ecit; ++cit)
278  {
279  csSet.insert((*cit));
280  }
281  }
282 }
283 
288 {
289  PTACallGraphNode* callGraphNode = getCallGraphNode(callee);
290  for(PTACallGraphNode::iterator it = callGraphNode->InEdgeBegin(), eit = callGraphNode->InEdgeEnd();
291  it!=eit; ++it)
292  {
293  for(PTACallGraphEdge::CallInstSet::const_iterator cit = (*it)->indirectCallsBegin(),
294  ecit = (*it)->indirectCallsEnd(); cit!=ecit; ++cit)
295  {
296  csSet.insert((*cit));
297  }
298  }
299 }
300 
305 {
306  CallEdgeMap::const_iterator it = indirectCallMap.begin();
307  CallEdgeMap::const_iterator eit = indirectCallMap.end();
308  for (; it != eit; ++it)
309  {
310  const FunctionSet& targets = it->second;
311  if (targets.empty() == false)
312  {
313  const CallICFGNode* cs = it->first;
314  const SVFFunction* func = cs->getCaller();
315  if (getCallGraphNode(func)->isReachableFromProgEntry() == false)
316  writeWrnMsg(func->getName() + " has indirect call site but not reachable from main");
317  }
318  }
319 }
320 
325 {
326  PTACallGraphNode* dstNode = getCallGraphNode(dstFn);
327 
328  std::stack<const PTACallGraphNode*> nodeStack;
329  NodeBS visitedNodes;
330  nodeStack.push(dstNode);
331  visitedNodes.set(dstNode->getId());
332 
333  while (nodeStack.empty() == false)
334  {
335  PTACallGraphNode* node = const_cast<PTACallGraphNode*>(nodeStack.top());
336  nodeStack.pop();
337 
338  if (node->getFunction() == srcFn)
339  return true;
340 
341  for (CallGraphEdgeConstIter it = node->InEdgeBegin(), eit = node->InEdgeEnd(); it != eit; ++it)
342  {
343  PTACallGraphEdge* edge = *it;
344  if (visitedNodes.test_and_set(edge->getSrcID()))
345  nodeStack.push(edge->getSrcNode());
346  }
347  }
348 
349  return false;
350 }
351 
355 void PTACallGraph::dump(const std::string& filename)
356 {
357  GraphPrinter::WriteGraphToFile(outs(), filename, this);
358 }
359 
361 {
362  SVF::ViewGraph(this, "Call Graph");
363 }
364 
365 namespace SVF
366 {
367 
371 template<>
373 {
374 
377  DOTGraphTraits(bool isSimple = false) :
378  DefaultDOTGraphTraits(isSimple)
379  {
380  }
381 
384  {
385  return "Call Graph";
386  }
389  {
390  return node->toString();
391  }
392 
394  {
395  const SVFFunction* fun = node->getFunction();
396  if (!SVFUtil::isExtCall(fun))
397  {
398  return "shape=box";
399  }
400  else
401  return "shape=Mrecord";
402  }
403 
404  template<class EdgeIter>
406  PTACallGraph*)
407  {
408 
409  //TODO: mark indirect call of Fork with different color
410  PTACallGraphEdge* edge = *(EI.getCurrent());
411  assert(edge && "No edge found!!");
412 
413  std::string color;
414 
416  {
417  color = "color=green";
418  }
419  else if (edge->getEdgeKind() == PTACallGraphEdge::TDForkEdge)
420  {
421  color = "color=blue";
422  }
423  else
424  {
425  color = "color=black";
426  }
427  if (0 != edge->getIndirectCalls().size())
428  {
429  color = "color=red";
430  }
431  return color;
432  }
433 
434  template<class EdgeIter>
436  {
437  PTACallGraphEdge* edge = *(EI.getCurrent());
438  assert(edge && "No edge found!!");
439 
440  std::string str;
441  std::stringstream rawstr(str);
442  rawstr << edge->getCallSiteID();
443 
444  return rawstr.str();
445  }
446 };
447 } // End namespace llvm
cJSON * item
Definition: cJSON.h:222
const char *const string
Definition: cJSON.h:172
const SVFFunction * getCalledFunction() const
Definition: ICFGNode.h:518
const SVFFunction * getCaller() const
Return callsite.
Definition: ICFGNode.h:470
NodeType * getSrcNode() const
Definition: GenericGraph.h:97
GEdgeKind getEdgeKind() const
Definition: GenericGraph.h:89
NodeID getDstID() const
Definition: GenericGraph.h:85
NodeID getSrcID() const
get methods of the components
Definition: GenericGraph.h:81
void addGNode(NodeID id, NodeType *node)
Add a Node.
Definition: GenericGraph.h:646
bool hasIncomingEdge() const
Has incoming/outgoing edge set.
Definition: GenericGraph.h:442
bool hasOutgoingEdge() const
Definition: GenericGraph.h:446
iterator OutEdgeEnd()
Definition: GenericGraph.h:458
iterator OutEdgeBegin()
iterators
Definition: GenericGraph.h:454
GEdgeSetTy::const_iterator const_iterator
Definition: GenericGraph.h:406
iterator InEdgeBegin()
Definition: GenericGraph.h:462
iterator InEdgeEnd()
Definition: GenericGraph.h:466
static void WriteGraphToFile(SVF::OutStream &O, const std::string &GraphName, const GraphType &GT, bool simple=false)
Definition: GraphPrinter.h:56
virtual const std::string toString() const
CallInstSet & getIndirectCalls()
Definition: PTACallGraph.h:99
void addDirectCallSite(const CallICFGNode *call)
Add direct and indirect callsite.
void addInDirectCallSite(const CallICFGNode *call)
Set< const CallICFGNode * > CallInstSet
Definition: PTACallGraph.h:55
CallSiteID getCallSiteID() const
Get direct and indirect calls.
Definition: PTACallGraph.h:83
virtual const std::string toString() const
PTACallGraphEdge::CallGraphEdgeSet::iterator iterator
Definition: PTACallGraph.h:179
const SVFFunction * getFunction() const
Get function of this call node.
Definition: PTACallGraph.h:198
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;.
Definition: PTACallGraph.h:268
void addEdge(PTACallGraphEdge *edge)
Add call graph edge.
Definition: PTACallGraph.h:443
void addIndirectCallGraphEdge(const CallICFGNode *cs, const SVFFunction *callerFun, const SVFFunction *calleeFun)
static IdToCallSiteMap idToCSMap
Map a callsite ID to a pair of call instruction and callee.
Definition: PTACallGraph.h:267
Set< const SVFFunction * > FunctionSet
Definition: PTACallGraph.h:251
Map< CallSiteID, CallSitePair > IdToCallSiteMap
Definition: PTACallGraph.h:250
PTACallGraph(CGEK k=NormCallGraph)
Constructor.
void addDirectCallGraphEdge(const CallICFGNode *call, const SVFFunction *callerFun, const SVFFunction *calleeFun)
Add direct/indirect 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.
Definition: PTACallGraph.h:266
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/Get CallSiteID.
Definition: PTACallGraph.h:354
FunToCallGraphNodeMap funToCallGraphNodeMap
Call Graph node map.
Definition: PTACallGraph.h:271
void getIndCallSitesInvokingCallee(const SVFFunction *callee, PTACallGraphEdge::CallInstSet &csSet)
CallGraphEdgeSet::const_iterator CallGraphEdgeConstIter
Definition: PTACallGraph.h:254
bool isReachableBetweenFunctions(const SVFFunction *srcFn, const SVFFunction *dstFn) const
Whether its reachable between two functions.
PTACallGraphNode * getCallGraphNode(NodeID id) const
Get call graph node.
Definition: PTACallGraph.h:339
CallInstToCallGraphEdgesMap callinstToCallGraphEdgesMap
Map a call instruction to its corresponding call edges.
Definition: PTACallGraph.h:272
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.
Definition: PTACallGraph.h:263
u32_t numOfResolvedIndCallEdge
Definition: PTACallGraph.h:275
Map< CallSitePair, CallSiteID > CallSiteToIdMap
Definition: PTACallGraph.h:249
NodeID getId() const
Get ID.
Definition: GenericGraph.h:260
const std::string & getName() const
Definition: SVFValue.h:243
const SVFValue * getValue() const
Get/has methods of the components.
Definition: SVFVariables.h:83
bool test_and_set(unsigned Idx)
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
const SVFVar * getForkedFun(const CallICFGNode *inst)
Return thread fork function.
Definition: SVFUtil.h:356
void writeWrnMsg(const std::string &msg)
Writes a message run through wrnMsg.
Definition: SVFUtil.cpp:66
std::ostream & outs()
Overwrite llvm::outs()
Definition: SVFUtil.h:50
for isBitcode
Definition: BasicTypes.h:68
unsigned CallSiteID
Definition: GeneralType.h:58
u32_t NodeID
Definition: GeneralType.h:55
void ViewGraph(const GraphType &G, const std::string &name, bool ShortNames=false, GraphProgram::Name Program=GraphProgram::DOT)
Definition: GraphWriter.h:371
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 *)