Static Value-Flow Analysis
Loading...
Searching...
No Matches
ICFG.cpp
Go to the documentation of this file.
1//===- ICFG.cpp -- Sparse value-flow graph-----------------------------------//
2//
3// SVF: Static Value-Flow Analysis
4//
5// Copyright (C) <2013-2018> <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 * ICFG.cpp
25 *
26 * Created on: Sep 11, 2018
27 * Author: Yulei Sui
28 */
29
30#include "Graphs/ICFG.h"
31#include "Graphs/CallGraph.h"
32#include "SVFIR/SVFIR.h"
33#include <Util/Options.h>
34
35using namespace SVF;
36using namespace SVFUtil;
37
38
40{
41 fun = f;
42 // if function is implemented
43 if (f->begin() != f->end())
44 {
45 bb = f->getEntryBlock();
46 }
47}
48
49const std::string ICFGNode::toString() const
50{
51 std::string str;
52 std::stringstream rawstr(str);
53 rawstr << "ICFGNode" << getId();
54 return rawstr.str();
55}
56
57void ICFGNode::dump() const
58{
59 outs() << this->toString() << "\n";
60}
61
62const std::string GlobalICFGNode::toString() const
63{
64 std::string str;
65 std::stringstream rawstr(str);
66 rawstr << "GlobalICFGNode" << getId();
67 for (const SVFStmt *stmt : getSVFStmts())
68 rawstr << "\n" << stmt->toString();
69 return rawstr.str();
70}
71
72
73const std::string IntraICFGNode::toString() const
74{
75 std::string str;
76 std::stringstream rawstr(str);
77 rawstr << "IntraICFGNode" << getId();
78 rawstr << " {fun: " << getFun()->getName() << getSourceLoc() << "}";
79 for (const SVFStmt *stmt : getSVFStmts())
80 rawstr << "\n" << stmt->toString();
81 if(getSVFStmts().empty())
82 rawstr << "\n" << valueOnlyToString();
83 return rawstr.str();
84}
85
86
87const std::string FunEntryICFGNode::toString() const
88{
89 std::string str;
90 std::stringstream rawstr(str);
91 rawstr << "FunEntryICFGNode" << getId();
92 rawstr << " {fun: " << getFun()->getName();
93 if (isExtCall(getFun())==false)
95 rawstr << "}";
96 for (const SVFStmt *stmt : getSVFStmts())
97 rawstr << "\n" << stmt->toString();
98 return rawstr.str();
99}
100
101const std::string FunEntryICFGNode::getSourceLoc() const
102{
103 return "function entry: " + fun->getSourceLoc();
104}
105
106const std::string FunExitICFGNode::toString() const
107{
108 const FunObjVar *fun = getFun();
109 std::string str;
110 std::stringstream rawstr(str);
111 rawstr << "FunExitICFGNode" << getId();
112 rawstr << " {fun: " << fun->getName();
113 // ensure the enclosing function has exit basic block
114 if (!isExtCall(fun) && fun->hasReturn())
116 rawstr << intraICFGNode->getSourceLoc();
117 rawstr << "}";
118 for (const SVFStmt *stmt : getSVFStmts())
119 rawstr << "\n" << stmt->toString();
120 return rawstr.str();
121}
122
123const std::string FunExitICFGNode::getSourceLoc() const
124{
125 return "function ret: " + fun->getSourceLoc();
126}
127
128const std::string CallICFGNode::toString() const
129{
130 std::string str;
131 std::stringstream rawstr(str);
132 rawstr << "CallICFGNode" << getId();
133 rawstr << " {fun: " << getFun()->getName() << ICFGNode::getSourceLoc() << "}";
134 for (const SVFStmt *stmt : getSVFStmts())
135 rawstr << "\n" << stmt->toString();
136 if(getSVFStmts().empty())
137 rawstr << "\n" << valueOnlyToString();
138 return rawstr.str();
139}
140
141const std::string RetICFGNode::toString() const
142{
143 std::string str;
144 std::stringstream rawstr(str);
145 rawstr << "RetICFGNode" << getId();
146 rawstr << " {fun: " << getFun()->getName() << ICFGNode::getSourceLoc() << "}";
147 for (const SVFStmt *stmt : getSVFStmts())
148 rawstr << "\n" << stmt->toString();
149 if(getSVFStmts().empty())
150 rawstr << "\n" << valueOnlyToString();
151 return rawstr.str();
152}
153
154const std::string ICFGEdge::toString() const
155{
156 std::string str;
157 std::stringstream rawstr(str);
158 rawstr << "ICFGEdge: [ICFGNode" << getDstID() << " <-- ICFGNode" << getSrcID() << "]\t";
159 return rawstr.str();
160}
161
162const std::string IntraCFGEdge::toString() const
163{
164 std::string str;
165 std::stringstream rawstr(str);
166 if(getCondition() == nullptr)
167 rawstr << "IntraCFGEdge: [ICFGNode" << getDstID() << " <-- ICFGNode" << getSrcID() << "]\t";
168 else
169 rawstr << "IntraCFGEdge: [ICFGNode" << getDstID() << " <-- ICFGNode" << getSrcID() << "] (branchCondition:" << getCondition()->toString() << ") (succCondValue: " << getSuccessorCondValue() << ") \t";
170
171 return rawstr.str();
172}
173
174const std::string CallCFGEdge::toString() const
175{
176 std::string str;
177 std::stringstream rawstr(str);
178 rawstr << "CallCFGEdge " << " [ICFGNode";
179 rawstr << getDstID() << " <-- ICFGNode" << getSrcID() << "]\t CallSite: " << getSrcNode()->toString() << "\t";
180 return rawstr.str();
181}
182
183const std::string RetCFGEdge::toString() const
184{
185 std::string str;
186 std::stringstream rawstr(str);
187 rawstr << "RetCFGEdge " << " [ICFGNode";
188 rawstr << getDstID() << " <-- ICFGNode" << getSrcID() << "]\t CallSite: " << getDstNode()->toString() << "\t";
189 return rawstr.str();
190}
191
194{
195 assert(SVFUtil::isa<RetICFGNode>(getDstNode()) && "not a RetICFGNode?");
196 return SVFUtil::cast<RetICFGNode>(getDstNode())->getCallICFGNode();
197}
198
207ICFG::ICFG(): totalICFGNode(0), globalBlockNode(nullptr)
208{
209}
210
212{
214 for (const auto &it: icfgNodeToSVFLoopVec)
215 {
216 for (const auto &loop: it.second)
217 {
218 loops.insert(loop);
219 }
220 }
221
222 for (const auto &it: loops)
223 {
224 delete it;
225 }
226 icfgNodeToSVFLoopVec.clear();
227}
228
230{
231 addGNode(node->getId(),node);
232}
233
239
240
243{
245 assert (entry && "fun entry not created in ICFGBuilder?");
246 return entry;
247}
250{
251 FunExitICFGNode* exit = getFunExitBlock(fun);
252 assert (exit && "fun exit not created in ICFGBuilder?");
253 return exit;
254}
255
260{
261 ICFGEdge edge(src,dst,kind);
264 if (outEdge && inEdge)
265 {
266 assert(outEdge == inEdge && "edges not match");
267 return outEdge;
268 }
269 else
270 return nullptr;
271}
272
277{
278 ICFGEdge edge(src,dst, kind);
281 if (outEdge && inEdge)
282 {
283 assert(outEdge == inEdge && "edges not match");
284 return outEdge;
285 }
286 else
287 return nullptr;
288}
289
294{
295 ICFGEdge edge(src,dst,kind);
298 if (outEdge && inEdge)
299 {
300 assert(outEdge == inEdge && "edges not match");
301 return outEdge;
302 }
303 else
304 return nullptr;
305}
306
307
312{
313
314 ICFGEdge * edge = nullptr;
315 u32_t counter = 0;
316 for (ICFGEdge::ICFGEdgeSetTy::iterator iter = src->OutEdgeBegin();
317 iter != src->OutEdgeEnd(); ++iter)
318 {
319 if ((*iter)->getDstID() == dst->getId() && (*iter)->getEdgeKind() == kind)
320 {
321 counter++;
322 edge = (*iter);
323 }
324 }
325 assert(counter <= 1 && "there's more than one edge between two ICFG nodes");
326 return edge;
327
328}
329
334{
337 if (edge != nullptr)
338 {
339 assert(edge->isIntraCFGEdge() && "this should be an intra CFG edge!");
340 return nullptr;
341 }
342 else
343 {
345 return (addICFGEdge(intraEdge) ? intraEdge : nullptr);
346 }
347}
348
353{
354
357 if (edge != nullptr)
358 {
359 assert(edge->isIntraCFGEdge() && "this should be an intra CFG edge!");
360 return nullptr;
361 }
362 else
363 {
365 intraEdge->setBranchCondVal(branchCondVal);
366 return (addICFGEdge(intraEdge) ? intraEdge : nullptr);
367 }
368}
369
370
375{
377 if (edge != nullptr)
378 {
379 assert(edge->isCallCFGEdge() && "this should be a call CFG edge!");
380 return nullptr;
381 }
382 else
383 {
385 return (addICFGEdge(callEdge) ? callEdge : nullptr);
386 }
387}
388
393{
395 if (edge != nullptr)
396 {
397 assert(edge->isRetCFGEdge() && "this should be a return CFG edge!");
398 return nullptr;
399 }
400 else
401 {
403 return (addICFGEdge(retEdge) ? retEdge : nullptr);
404 }
405}
406
407
411void ICFG::dump(const std::string& file, bool simple)
412{
414}
415
420{
421 SVF::ViewGraph(this, "Interprocedural Control-Flow Graph");
422}
423
428{
429 CallGraph::CallEdgeMap::const_iterator iter = callgraph->getIndCallMap().begin();
430 CallGraph::CallEdgeMap::const_iterator eiter = callgraph->getIndCallMap().end();
431 for (; iter != eiter; iter++)
432 {
433 CallICFGNode* callBlockNode = const_cast<CallICFGNode*>(iter->first);
434 assert(callBlockNode->isIndirectCall() && "this is not an indirect call?");
435 const CallGraph::FunctionSet & functions = iter->second;
436 for (CallGraph::FunctionSet::const_iterator func_iter = functions.begin(); func_iter != functions.end(); func_iter++)
437 {
438 const FunObjVar* callee = *func_iter;
439 RetICFGNode* retBlockNode = const_cast<RetICFGNode*>(callBlockNode->getRetICFGNode());
441 if (isExtCall(callee))
442 addIntraEdge(callBlockNode, retBlockNode);
443 else
444 {
447 if(ICFGEdge* callEdge = addCallEdge(callBlockNode, calleeEntryNode))
448 {
449 for (const SVFStmt *stmt : callBlockNode->getSVFStmts())
450 {
451 if(const CallPE *callPE = SVFUtil::dyn_cast<CallPE>(stmt))
452 {
453 if(callPE->getFunEntryICFGNode() == calleeEntryNode)
454 SVFUtil::cast<CallCFGEdge>(callEdge)->addCallPE(callPE);
455 }
456 }
457 }
459 {
460 for (const SVFStmt *stmt : retBlockNode->getSVFStmts())
461 {
462 if(const RetPE *retPE = SVFUtil::dyn_cast<RetPE>(stmt))
463 {
464 if(retPE->getFunExitICFGNode() == calleeExitNode)
465 SVFUtil::cast<RetCFGEdge>(retEdge)->addRetPE(retPE);
466 }
467 }
468 }
469
473 }
474
475 }
476 }
477 // dump ICFG
478 if (Options::DumpICFG())
479 {
480 dump("icfg_final");
481 }
482}
483
487namespace SVF
488{
489template<>
491{
492
494 DOTGraphTraits(bool isSimple = false) :
495 DOTGraphTraits<SVFIR*>(isSimple)
496 {
497 }
498
500 static std::string getGraphName(ICFG*)
501 {
502 return "ICFG";
503 }
504
505 std::string getNodeLabel(NodeType *node, ICFG *graph)
506 {
507 return getSimpleNodeLabel(node, graph);
508 }
509
511 static std::string getSimpleNodeLabel(NodeType *node, ICFG*)
512 {
513 return node->toString();
514 }
515
516 static bool isNodeHidden(ICFGNode *node, ICFG *)
517 {
519 return false;
520 else
521 return node->getInEdges().empty() && node->getOutEdges().empty();
522 }
523
524 static std::string getNodeAttributes(NodeType *node, ICFG*)
525 {
526 std::string str;
527 std::stringstream rawstr(str);
528
529 if(SVFUtil::isa<IntraICFGNode>(node))
530 {
531 rawstr << "color=black";
532 }
533 else if(SVFUtil::isa<FunEntryICFGNode>(node))
534 {
535 rawstr << "color=yellow";
536 }
537 else if(SVFUtil::isa<FunExitICFGNode>(node))
538 {
539 rawstr << "color=green";
540 }
541 else if(SVFUtil::isa<CallICFGNode>(node))
542 {
543 rawstr << "color=red";
544 }
545 else if(SVFUtil::isa<RetICFGNode>(node))
546 {
547 rawstr << "color=blue";
548 }
549 else if(SVFUtil::isa<GlobalICFGNode>(node))
550 {
551 rawstr << "color=purple";
552 }
553 else
554 assert(false && "no such kind of node!!");
555
556 rawstr << "";
557
558 return rawstr.str();
559 }
560
561 template<class EdgeIter>
562 static std::string getEdgeAttributes(NodeType*, EdgeIter EI, ICFG*)
563 {
564 ICFGEdge* edge = *(EI.getCurrent());
565 assert(edge && "No edge found!!");
566 if (SVFUtil::isa<CallCFGEdge>(edge))
567 return "style=solid,color=red";
568 else if (SVFUtil::isa<RetCFGEdge>(edge))
569 return "style=solid,color=blue";
570 else
571 return "style=solid";
572 return "";
573 }
574
575 template<class EdgeIter>
577 {
578 ICFGEdge* edge = *(EI.getCurrent());
579 assert(edge && "No edge found!!");
580
581 std::string str;
582 std::stringstream rawstr(str);
583 if (CallCFGEdge* dirCall = SVFUtil::dyn_cast<CallCFGEdge>(edge))
584 rawstr << dirCall->getSrcNode();
585 else if (RetCFGEdge* dirRet = SVFUtil::dyn_cast<RetCFGEdge>(edge))
586 {
587 if(RetICFGNode* ret = SVFUtil::dyn_cast<RetICFGNode>(dirRet->getDstNode()))
588 rawstr << ret->getCallICFGNode();
589 }
590
591 return rawstr.str();
592 }
593};
594} // End namespace llvm
virtual const std::string toString() const
Definition ICFG.cpp:174
CallEdgeMap & getIndCallMap()
Get callees from an indirect callsite.
Definition CallGraph.h:331
Set< const FunObjVar * > FunctionSet
Definition CallGraph.h:247
const std::string toString() const override
Definition ICFG.cpp:128
const RetICFGNode * getRetICFGNode() const
Return callsite.
Definition ICFGNode.h:439
bool isIndirectCall() const
Return true if this is an indirect call.
Definition ICFGNode.h:464
FunEntryICFGNode(NodeID id, const FunObjVar *f)
Definition ICFG.cpp:39
const FunObjVar * getFun() const override
Return function.
Definition ICFGNode.h:284
const std::string toString() const override
Definition ICFG.cpp:87
const std::string getSourceLoc() const override
Definition ICFG.cpp:101
const std::string toString() const override
Definition ICFG.cpp:106
const FunObjVar * getFun() const override
Return function.
Definition ICFGNode.h:353
const std::string getSourceLoc() const override
Definition ICFG.cpp:123
const SVFBasicBlock * getExitBB() const
bool hasReturn() const
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.
bool hasIncomingEdge() const
Has incoming/outgoing edge set.
bool hasOutgoingEdge() const
iterator OutEdgeEnd()
const GEdgeSetTy & getOutEdges() const
const GEdgeSetTy & getInEdges() const
iterator OutEdgeBegin()
iterators
const std::string toString() const override
Definition ICFG.cpp:62
static void WriteGraphToFile(SVF::OutStream &O, const std::string &GraphName, const GraphType &GT, bool simple=false)
virtual const std::string toString() const
Definition ICFG.cpp:154
const SVFBasicBlock * bb
Definition ICFGNode.h:145
void dump() const
Definition ICFG.cpp:57
virtual const FunObjVar * getFun() const
Return the function of this ICFGNode.
Definition ICFGNode.h:74
const FunObjVar * fun
Definition ICFGNode.h:144
virtual const std::string toString() const
Definition ICFG.cpp:49
const SVFStmtList & getSVFStmts() const
Definition ICFGNode.h:115
void view()
View graph from the debugger.
Definition ICFG.cpp:419
ICFGEdge * hasThreadICFGEdge(ICFGNode *src, ICFGNode *dst, ICFGEdge::ICFGEdgeK kind)
Definition ICFG.cpp:293
bool addICFGEdge(ICFGEdge *edge)
Add ICFG edge, only used by addIntraEdge, addCallEdge, addRetEdge etc.
Definition ICFG.h:252
void removeICFGEdge(ICFGEdge *edge)
Remove a ICFG edge.
Definition ICFG.h:147
ICFGEdge * getICFGEdge(const ICFGNode *src, const ICFGNode *dst, ICFGEdge::ICFGEdgeK kind)
Get a SVFG edge according to src and dst.
Definition ICFG.cpp:311
ICFG()
Constructor.
Definition ICFG.cpp:207
void checkIntraEdgeParents(const ICFGNode *srcNode, const ICFGNode *dstNode)
sanitize Intra edges, verify that both nodes belong to the same function.
Definition ICFG.h:161
ICFGEdge * addCallEdge(ICFGNode *srcNode, ICFGNode *dstNode)
Definition ICFG.cpp:374
ICFGNodeToSVFLoopVec icfgNodeToSVFLoopVec
map ICFG node to the SVF loops where it resides
Definition ICFG.h:72
FunExitICFGNode * getFunExitICFGNode(const FunObjVar *fun)
Add a function exit node.
Definition ICFG.cpp:249
ICFGEdge * hasInterICFGEdge(ICFGNode *src, ICFGNode *dst, ICFGEdge::ICFGEdgeK kind)
Definition ICFG.cpp:276
GlobalICFGNode * globalBlockNode
unique basic block for all globals
Definition ICFG.h:71
virtual void addGlobalICFGNode(GlobalICFGNode *globalICFGNode)
Definition ICFG.cpp:234
void dump(const std::string &file, bool simple=false)
Dump graph into dot file.
Definition ICFG.cpp:411
ICFGEdge * addRetEdge(ICFGNode *srcNode, ICFGNode *dstNode)
Definition ICFG.cpp:392
void updateCallGraph(CallGraph *callgraph)
update ICFG for indirect calls
Definition ICFG.cpp:427
ICFGEdge * hasIntraICFGEdge(ICFGNode *src, ICFGNode *dst, ICFGEdge::ICFGEdgeK kind)
Whether we has a SVFG edge.
Definition ICFG.cpp:259
ICFGEdge * addConditionalIntraEdge(ICFGNode *srcNode, ICFGNode *dstNode, s64_t branchCondVal)
Definition ICFG.cpp:352
FunExitICFGNode * getFunExitBlock(const FunObjVar *fun)
Get/Add a function exit node.
Definition ICFG.h:271
ICFGEdge * addIntraEdge(ICFGNode *srcNode, ICFGNode *dstNode)
Add intraprocedural and interprocedural control-flow edges.
Definition ICFG.cpp:333
FunEntryICFGNode * getFunEntryICFGNode(const FunObjVar *fun)
Add a function entry node.
Definition ICFG.cpp:242
~ICFG() override
Destructor.
Definition ICFG.cpp:211
virtual void addICFGNode(ICFGNode *node)
Add a ICFG node.
Definition ICFG.cpp:229
FunEntryICFGNode * getFunEntryBlock(const FunObjVar *fun)
Get/Add a function entry node.
Definition ICFG.h:262
s64_t getSuccessorCondValue() const
Definition ICFGEdge.h:144
virtual const std::string toString() const
Definition ICFG.cpp:162
const SVFVar * getCondition() const
Definition ICFGEdge.h:139
const std::string toString() const override
Definition ICFG.cpp:73
static const Option< bool > ShowHiddenNode
Definition Options.h:225
static const Option< bool > DumpICFG
Definition Options.h:120
const CallICFGNode * getCallSite() const
Return call ICFGNode at the callsite.
Definition ICFG.cpp:193
virtual const std::string toString() const
Definition ICFG.cpp:183
const std::string toString() const override
Definition ICFG.cpp:141
const ICFGNode * front() const
NodeID getId() const
Get ID.
Definition SVFValue.h:160
virtual const std::string getSourceLoc() const
Definition SVFValue.h:196
virtual const std::string & getName() const
Definition SVFValue.h:186
const std::string valueOnlyToString() const
Definition LLVMUtil.cpp:739
virtual const std::string toString() const
Get string representation.
bool isExtCall(const FunObjVar *fun)
Definition SVFUtil.cpp:437
std::ostream & outs()
Overwrite llvm::outs()
Definition SVFUtil.h:52
for isBitcode
Definition BasicTypes.h:68
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:74
unsigned u32_t
Definition GeneralType.h:47
signed long long s64_t
Definition GeneralType.h:50
std::string getNodeLabel(NodeType *node, ICFG *graph)
Definition ICFG.cpp:505
static std::string getGraphName(ICFG *)
Return name of the graph.
Definition ICFG.cpp:500
static bool isNodeHidden(ICFGNode *node, ICFG *)
Definition ICFG.cpp:516
static std::string getSimpleNodeLabel(NodeType *node, ICFG *)
Return the label of an ICFG node.
Definition ICFG.cpp:511
static std::string getEdgeSourceLabel(NodeType *, EdgeIter EI)
Definition ICFG.cpp:576
static std::string getEdgeAttributes(NodeType *, EdgeIter EI, ICFG *)
Definition ICFG.cpp:562
static std::string getNodeAttributes(NodeType *node, ICFG *)
Definition ICFG.cpp:524
DOTGraphTraits(bool isSimple=false)
Definition ICFG.cpp:494